diff --git a/chrome/content/zotero/preferences/preferences.js b/chrome/content/zotero/preferences/preferences.js
index eb5cb0798..a9650bf5b 100644
--- a/chrome/content/zotero/preferences/preferences.js
+++ b/chrome/content/zotero/preferences/preferences.js
@@ -31,6 +31,7 @@ function init()
rows[i].firstChild.nextSibling.value = Zotero.isMac ? 'Cmd+Shift+' : 'Ctrl+Alt+';
}
+ refreshStylesList();
populateQuickCopyList();
updateQuickCopyInstructions();
initSearchPane();
@@ -912,4 +913,134 @@ function onOpenURLSelected()
function onOpenURLCustomized()
{
document.getElementById('openURLMenu').value = "custom";
+}
+
+/** STYLES **/
+
+/**
+ * Refreshes the list of styles in the styles pane
+ **/
+function refreshStylesList(cslID) {
+ var treechildren = document.getElementById('styleManager-rows');
+ while (treechildren.hasChildNodes()) {
+ treechildren.removeChild(treechildren.firstChild);
+ }
+
+ var sql = "SELECT cslID, title, updated FROM csl ORDER BY title";
+ var styleData = Zotero.DB.query(sql);
+ if (!styleData) return;
+
+ Zotero.debug("ASKED FOR "+cslID);
+
+ var selectIndex = false;
+ for (var i=0; i
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chrome/content/zotero/xpcom/cite.js b/chrome/content/zotero/xpcom/cite.js
index 34048bc92..469d77ffa 100644
--- a/chrome/content/zotero/xpcom/cite.js
+++ b/chrome/content/zotero/xpcom/cite.js
@@ -25,9 +25,9 @@
* this class handles pulling the CSL file and item data out of the database,
* while CSL, below, handles the actual generation of the bibliography
*/
+default xml namespace = "http://purl.org/net/xbiblio/csl";
+
Zotero.Cite = new function() {
- default xml namespace = "http://purl.org/net/xbiblio/csl";
-
var _lastCSL = null;
var _lastStyle = null;
@@ -35,6 +35,7 @@ Zotero.Cite = new function() {
this.getStyleClass = getStyleClass;
this.getStyle = getStyle;
this.installStyle = installStyle;
+ this.deleteStyle = deleteStyle;
/*
* returns an associative array of cslID => styleName pairs
@@ -105,8 +106,8 @@ Zotero.Cite = new function() {
}
if (!xml || error) {
- alert(Zotero.getString('styles.installError', loadURI));
- return;
+ alert(Zotero.getString('styles.installError', (loadURI ? loadURI : "This")));
+ return false;
}
var uri = xml.info.id.toString();
@@ -123,10 +124,18 @@ Zotero.Cite = new function() {
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
if (existingTitle) {
- var text = Zotero.getString('styles.updateStyle', [existingTitle, title, loadURI]);
+ if(loadURI) {
+ var text = Zotero.getString('styles.updateStyleURI', [existingTitle, title, loadURI]);
+ } else {
+ var text = Zotero.getString('styles.updateStyle', [existingTitle, title]);
+ }
}
else {
- var text = Zotero.getString('styles.installStyle', [title, loadURI]);
+ if(loadURI) {
+ var text = Zotero.getString('styles.installStyleURI', [title, loadURI]);
+ } else {
+ var text = Zotero.getString('styles.installStyle', [title]);
+ }
}
var acceptButton = Zotero.getString('general.install');
@@ -142,6 +151,27 @@ Zotero.Cite = new function() {
var sql = "REPLACE INTO csl VALUES (?,?,?,?)";
Zotero.DB.query(sql, [uri, updated, title, cslString]);
alert(Zotero.getString('styles.installed', title));
+ return uri;
+ }
+ }
+
+ /**
+ * deletes a style
+ **/
+ function deleteStyle(uri) {
+ var sql = "SELECT title FROM csl WHERE cslID=?";
+ var title = Zotero.DB.valueQuery(sql, uri);
+
+ if(!title) throw "Cite: style to delete does not exist!"
+
+ var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+ .getService(Components.interfaces.nsIPromptService);
+
+ var text = Zotero.getString('styles.deleteStyle', [title]);
+
+ if(ps.confirm(null, '', text)) {
+ var sql = "DELETE FROM csl WHERE cslID=?";
+ Zotero.DB.query(sql, uri);
}
}
}
@@ -277,7 +307,7 @@ Zotero.Cite.MIMEHandler.StreamListener.prototype.onStopRequest = function(channe
* want to use the Scholar data model, but does want to use CSL in JavaScript
*/
Zotero.CSL = function(csl) {
- default xml namespace = "http://purl.org/net/xbiblio/csl";
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with ({});
this._csl = new XML(Zotero.CSL.Global.cleanXML(csl));
@@ -292,6 +322,7 @@ Zotero.CSL = function(csl) {
Zotero.debug("CSL: style class is "+this.class);
this.hasBibliography = (this._csl.bibliography.length() ? 1 : 0);
+ Zotero.debug("hasBibliography "+this.hasBibliography);
}
/*
@@ -344,6 +375,8 @@ Zotero.CSL._firstNameRegexp = /^[^\s]*/;
Zotero.CSL._textCharRegexp = /[a-zA-Z0-9]/;
Zotero.CSL._numberRegexp = /\d+/;
Zotero.CSL.prototype.formatCitation = function(citation, format) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
var context = this._csl.citation;
if(!context) {
throw "CSL: formatCitation called on style with no citation context";
@@ -535,6 +568,8 @@ Zotero.CSL.prototype.formatCitation = function(citation, format) {
* create a bibliography
*/
Zotero.CSL.prototype.formatBibliography = function(itemSet, format) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
var context = this._csl.bibliography;
if(!context.length()) {
context = this._csl.citation;
@@ -770,6 +805,8 @@ Zotero.CSL.prototype._getTerm = function(term, plural, form, includePeriod) {
* non-Western names better than ours, this would be the function to change
*/
Zotero.CSL.prototype._processNames = function(item, element, formattedString, context, citationItem, variables) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
var children = element.children();
if(!children.length()) return false;
var variableSucceeded = false;
@@ -953,6 +990,8 @@ Zotero.CSL.prototype._processNames = function(item, element, formattedString, co
*/
Zotero.CSL.prototype._processElements = function(item, element, formattedString,
context, citationItem, ignore, isSingle) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
if(!ignore) {
ignore = [[], []];
// ignore[0] is for variables; ignore[1] is for macros
@@ -1381,6 +1420,8 @@ Zotero.CSL.prototype._processElements = function(item, element, formattedString,
* Returns -1 if A comes before B, 1 if B comes before A, or 0 if they are equal
*/
Zotero.CSL.prototype._compareItem = function(a, b, context, cache) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
var sortA = [];
var sortB = [];
@@ -1496,6 +1537,8 @@ Zotero.CSL.prototype.cachedSort = function(items, context, field) {
}
Zotero.CSL.prototype.getEqualCitations = function(items) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
var citationsEqual = [];
if(items) {
@@ -1524,6 +1567,8 @@ Zotero.CSL.prototype.getEqualCitations = function(items) {
* Compares two citations; returns true if they are different, false if they are equal
*/
Zotero.CSL.prototype.compareCitations = function(a, b, context) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
if((!a && b) || (a && !b)) {
return true;
} else if(!a && !b) {
@@ -1549,7 +1594,7 @@ Zotero.CSL.Global = new function() {
this.cleanXML = cleanXML;
this.parseLocales = parseLocales;
- default xml namespace = "http://purl.org/net/xbiblio/csl";
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
this.ns = "http://purl.org/net/xbiblio/csl";
this.__defineGetter__("locale", function() {
@@ -1810,6 +1855,8 @@ Zotero.CSL.CitationItem = function(item) {
* the Citation object represents a citation.
*/
Zotero.CSL.Citation = function(citationItems, csl) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
if(csl) {
this._csl = csl;
this._citation = csl._csl.citation;
@@ -1893,8 +1940,6 @@ Zotero.CSL.Citation.prototype.clone = function() {
* with "_") are implemented.
*/
Zotero.CSL.Item = function(item) {
- default xml namespace = "http://purl.org/net/xbiblio/csl";
-
if(item instanceof Zotero.Item) {
this.zoteroItem = item;
} else if(parseInt(item, 10) == item) {
@@ -2337,7 +2382,7 @@ Zotero.CSL.Item.Name = function(zoteroCreator) {
* lastName - last name
*/
Zotero.CSL.Item.Name.prototype.getNameVariable = function(variable) {
- return this._zoteroCreator[variable] ? this._zoteroCreator[variable] : "";
+ return this._zoteroCreator.ref[variable] ? this._zoteroCreator.ref[variable] : "";
}
/*
@@ -2345,7 +2390,7 @@ Zotero.CSL.Item.Name.prototype.getNameVariable = function(variable) {
* in an item wrapper.
*/
Zotero.CSL.ItemSet = function(items, csl) {
- default xml namespace = "http://purl.org/net/xbiblio/csl";
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
this.csl = csl;
@@ -2465,6 +2510,8 @@ Zotero.CSL.ItemSet.prototype.remove = function(items) {
* citations have changed
*/
Zotero.CSL.ItemSet.prototype.resort = function() {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
// sort
this.items = this.csl.cachedSort(this.items, this.bibliography);
@@ -2722,7 +2769,7 @@ Zotero.CSL.ItemSet.prototype._copyDisambiguation = function(fromItem, toItem) {
}
Zotero.CSL.FormattedString = function(context, format, delimiter, subsequent) {
- default xml namespace = "http://purl.org/net/xbiblio/csl";
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
this.context = context;
this.option = context ? context.option : new XMLList();
@@ -2754,6 +2801,8 @@ Zotero.CSL.FormattedString._punctuation = "!.,?:";
* attaches another formatted string to the end of the current one
*/
Zotero.CSL.FormattedString.prototype.concat = function(formattedString, element) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
if(!formattedString || !formattedString.string) {
return false;
}
@@ -2798,6 +2847,7 @@ Zotero.CSL.FormattedString._rtfEscapeFunction = function(aChar) {
* appends a string (with format parameters) to the current one
*/
Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDelimit, dontEscape) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
if(!string && string !== 0) return false;
diff --git a/chrome/content/zotero/xpcom/enstyle.js b/chrome/content/zotero/xpcom/enstyle.js
new file mode 100644
index 000000000..971daf97a
--- /dev/null
+++ b/chrome/content/zotero/xpcom/enstyle.js
@@ -0,0 +1,1374 @@
+/*
+ ***** 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 *****
+*/
+
+/**
+ * Constructor for EndNote converter
+ * @constructor
+ **/
+Zotero.ENConverter = function(styleData, date, fileTitle) {
+ this.data = styleData;
+ if(date) this.date = date;
+ if(fileTitle) this.fileTitle = fileTitle;
+
+ var formatCode = this.data.substr(8, 8);
+ if(formatCode != "RSFTSTYL" && formatCode != "ENDNENFT") {
+ throw "Zotero.ENConverter: File not recognized. Is this a style file?";
+ }
+}
+
+/**
+ * Mappings for item types
+ *
+ * Those in lower case are not in the mapping list because they are implemented
+ * elsewhere in the code.
+ * Those in upper case are not implemented.
+ **/
+Zotero.ENConverter.typeMappings = {
+ "\x00":"article-journal",
+ "\x01":"book",
+ "\x02":"thesis",
+// \x03 - CONFERENCE PROCEEDINGS
+ "\x04":"personal_communication",
+ "\x05":"article-newspaper",
+// \x06 - PROGRAM
+ "\x07":"chapter",
+ "\x08":"article-magazine",
+// \x09 - Edited Book
+ "\x0A":"report",
+ "\x0B":"map",
+// \x0C - AUDIOVISUAL MATERIAL
+ "\x0D":"graphic",
+// \x0E - UNUSED 1
+ "\x0F":"patent",
+ "\x10":"webpage",
+ "\x11":"bill",
+ "\x12":"legal_case",
+// \x13 - HEARING
+ "\x14":"manuscript",
+ "\x15":"motion_picture",
+// \x16 - STATUTE
+// \x17 - UNUSED 2
+// \x18 - UNUSED 3
+ "\x19":"figure",
+// \x1A - CHART OR TABLE
+// \x1B - EQUATION
+// \x1C - Electronic Article
+// \x1D - Electronic Book
+// \x1E - ONLINE DATABASE
+// \x1F - Generic
+// \x20 - GOVERNMENT DOCUMENT
+ "\x21":"paper-conference",
+// \x22 - ONLINE MULTIMEDIA
+// \x23 - CLASSICAL WORK
+ "\x24":"legislation",
+// \x25 - UNPUBLISHED WORK
+// \x26 - ANCIENT TEXT
+ "\x27":"entry-dictionary",
+ "\x28":"entry-encyclopedia"
+// \x29 - GRANT
+};
+
+/**
+ * List of CSL fallback types
+ **/
+Zotero.ENConverter.fallbackTypes = {
+ "book":true,
+ "chapter":true,
+ "article":true
+}
+
+/**
+ * List of types that we should parse, but not map directly
+ **/
+Zotero.ENConverter.supplementalTypes = {
+ "\x09":true, // Edited Book (use conditional on book)
+ "\x1C":true, // Electronic Article (use conditional on article)
+ "\x1D":true, // Electronic Book (use conditional on book)
+ "\x1F":true // Generic (use for all unspecified types)
+};
+
+/**
+ * Mappings for text variables
+ *
+ * Those in lower case are not in the mapping list because they are implemented
+ * elsewhere in the code.
+ * Those in upper case are not implemented.
+ **/
+Zotero.ENConverter.variableMappings = {
+// \x01 - TYPE OF REFERENCE
+// \x02 - Author/Editor
+// \x03 - Year
+ "\x05":"page",
+// \x06 - Secondary/Series/Publication Title/Bill Code
+ "\x07":"volume",
+ "\x08":"issue",
+ "\x09":"number-of-volumes",
+// \x0A - Secondary/Series Author
+ "\x0B":"publisher-place",
+ "\x0C":"publisher",
+// \x0D - Translator/Subsidiary Author
+// \x0F - KEYWORD
+ "\x10":"genre",
+// \x11 - Date
+ "\x12":"abstract",
+ "\x13":"citation-label",
+ "\x14":"URL",
+// \x15 - TERTIARY TITLE
+// \x16 - TERTIARY AUTHOR
+ "\x17":"note",
+ "\x18":"ISBN",
+// \x19 - CUSTOM 1
+// \x1A - CUSTOM 2
+// \x1B - CUSTOM 3
+// \x1C - CUSTOM 4
+// \x1D - ABBREVIATION
+// \x1E - ACCESSION NUMBER
+// \x1F - CALL NUMBER
+// \x21 - CUSTOM 5
+// \x22 - CUSTOM 6
+// \x23 - SECTION/PAGES CITED/Chapter Title
+// \x24 - ORIGINAL PUBLICATION
+// \x25 - REPRINT EDITION
+// \x26 - REVIEWED ITEM
+// \x27 - AUTHOR ADDRESS
+// \x28 - IMAGE
+// \x29 - CAPTION
+// \x2A - CUSTOM 7
+// \x2B - ELECTRONIC RESOURCE NUMBER
+// \x2C - LINK TO PDF
+// \x2D - TRANSLATED AUTHOR
+// \x2E - TRANSLATED TITLE
+// \x2F - NAME OF DATABASE
+// \x30 - DATABASE PROVIDER
+// \x31 - RESEARCH NOTES
+// \x32 - LANGUAGE
+// \x33 - accessed
+// \x34 - LAST MODIFIED
+// \x00\x40 - citation
+ "\x01\x40":"citation-number",
+// \x02\x40 - RECORD NUMBER
+ "\x06\x40":"locator"
+}
+
+/**
+ * List of types that we should map to macros.
+ **/
+Zotero.ENConverter.macroVariables = {
+ "\x02":["author-citation", "author-bibliography"], // Author
+ "\x03":["year-citation", "year-bibliography"], // Year
+ "\x04":["title-citation", "title-bibliography"], // Title/Book Title
+ "\x06":"secondary_title", // Series/Publication Title
+ "\x0A":["secondary_author-citation", "secondary_author-bibliography"], // Editor/Series Editor
+ "\x0D":["translator-citation", "translator-bibliography"], // Translator
+ "\x0E":"edition", // Edition
+ "\x11":"date", // Date
+ "\x15":"tertiary_title",
+ "\x16":["tertiary_author-citation", "tertiary_author-bibliography"], // Chapter Series Editor
+ "\x20":"short-title", // Short Title/Short Book Title
+ "\x23":"chapter_title", // Chapter Title
+ "\x33":"accessed",
+ "\x00\x40":"citation" // Citation
+};
+
+/**
+ * List of types where \x06 maps to collection-title (rather than
+ * container-title)
+ **/
+Zotero.ENConverter.seriesTypes = "book report map motion_picture";
+Zotero.ENConverter.seriesCodes = ["\x01", "\x09", "\x0A", "\x0B", "\x15", "\x1D"];
+
+/**
+ * Generates the element for the style
+ **/
+Zotero.ENConverter.prototype.parseInfo = function() {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
+ var guid = "";
+ for(var i=0; i<16; i++) {
+ var bite = Math.floor(Math.random() * 255);
+
+ if(i == 4 || i == 6 || i == 8 || i == 10) {
+ guid += "-";
+
+ // version
+ if(i == 6) bite = bite & 0x0f | 0x40;
+ // variant
+ if(i == 8) bite = bite & 0x3f | 0x80;
+ }
+ var str = bite.toString(16);
+ guid += str.length == 1 ? '0' + str : str;
+ }
+
+ this.xml.info.id = "urn:uuid:"+guid;
+ if(this.fileTitle) {
+ var title = this.fileTitle;
+ } else {
+ var title = this.convertFromUTF16(this.findField(this.fields, "\x10")[0].data.replace("\xFB", "", "g"));
+ if(!title) title = "Untitled Style";
+ }
+ this.xml.info.title = title;
+
+ if(this.date) {
+ var date = this.date;
+ } else {
+ var date = new Date();
+ }
+
+ var y = date.getFullYear().toString();
+ var m = (date.getUTCMonth()+1).toString();
+ var d = date.getUTCDay().toString();
+ var h = date.getUTCHours().toString();
+ var n = date.getUTCMinutes().toString();
+ var s = date.getUTCSeconds().toString();
+ if(m.length == 1) m = "0"+m;
+ if(d.length == 1) d = "0"+d;
+ if(h.length == 1) h = "0"+h;
+ if(n.length == 1) n = "0"+n;
+ if(s.length == 1) s = "0"+s;
+ this.xml.info.updated = y+"-"+m+"-"+d+"T"+h+":"+n+":"+s+"+00:00";
+}
+
+/**
+ * Converts a little endian binary representation of an integer into a JS integer
+ *
+ * @param {String} binaryData The binary representation of the integer
+ * @returns The JS integer
+ * @type Integer
+ **/
+Zotero.ENConverter.prototype.parseInt = function(binaryData) {
+ if(binaryData.length == 4) {
+ // since this is so common, avoid overhead
+ return binaryData.charCodeAt(0)+binaryData.charCodeAt(1)*0x100
+ +binaryData.charCodeAt(2)*0x10000+binaryData.charCodeAt(3)*0x1000000;
+ } else {
+ var integer = 0;
+ for(var i=0; i tags instead of
+ * plain text
+ *
+ * @returns Plain text, or the XML representation as tags, depending on
+ * the richOutput parameter
+ **/
+Zotero.ENConverter.prototype.parseFormattedString = function(string, richOutput) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
+ var stringLength = this.parseInt(string.substr(4, 4))-8;
+ if(stringLength == 0) return richOutput ? false : "";
+
+ var newString = this.convertFromUTF16(string.substr(8, stringLength));
+
+ // strip out chars that shouldn't be there
+ newString = newString.replace(/[\x00-\x08\x0E-\x1F]/g, "");
+
+ if(richOutput) {
+ var formattedXML = new XML();
+ var lastOffset = 0;
+ var style = false;
+
+ var i = stringLength + 8;
+ while(i < string.length) {
+ var length = this.parseInt(string.substr(i+4, 4));
+ var data = string.substr(i+8, length-8);
+ if(length == 0) break;
+ var startOffset = this.parseInt(data.substr(4, 4));
+
+ // add term containing text from last element to new element
+ var text = newString.substring(lastOffset, startOffset);
+ if(lastOffset != startOffset) {
+ var textElement = ;
+ if(style) this.applyFormattingAttributes(textElement, style);
+ formattedXML += textElement;
+ }
+
+ var style = data.substr(data.indexOf("&")+4, 4);
+ lastOffset = startOffset;
+
+ i += length + length % 4;
+ }
+
+ if(lastOffset != newString.length) {
+ var text = newString.substring(lastOffset);
+ var textElement = ;
+ if(style) this.applyFormattingAttributes(textElement, style);
+ formattedXML += textElement;
+ }
+
+ return formattedXML;
+ } else {
+ return newString;
+ }
+}
+
+
+/**
+ * Applies the formatting attributes specified by a binary string to a given
+ * text element
+ *
+ * @param {XML} element The element to which the formatting attributes will be
+ * applied
+ * @param {String} formatCode The binary format string
+ **/
+Zotero.ENConverter.prototype.applyFormattingAttributes = function(element, formatCode) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
+ if(!formatCode) return;
+
+ var binaryDigits = this.parseInt(formatCode).toString(2);
+ // pad to 7 digits
+ while(binaryDigits.length < 7) binaryDigits = "0"+binaryDigits;
+
+ if(binaryDigits[6] == "1") { // italics
+ element["@font-weight"] = "bold";
+ }
+ if(binaryDigits[5] == "1") { // bold
+ element["@font-style"] = "italic";
+ }
+ if(binaryDigits[4] == "1") { // underline
+ element["@text-decoration"] = "underline";
+ }
+ // what are bits 3 and 2?
+ if(binaryDigits[1] == "1") { // subscript
+ element["@vertical-align"] = "sup";
+ } else if(binaryDigits[0] == "1") { // superscript
+ element["@vertical-align"] = "sub";
+ }
+}
+
+/**
+ * Parses format to create a hierarchical data structure
+ *
+ * @param {String} styleData The EndNote style file, as binary data
+ * @returns An array of objects representing the structure of the EndNote file
+ * @type Array
+ **/
+Zotero.ENConverter.prototype.parseFormat = function(styleData) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
+ var fields = [];
+
+ var offset1 = styleData.indexOf("\x10");
+ var offset2 = styleData.indexOf("\x11");
+ if(offset1 != -1 && (offset2 == -1 || offset1 < offset2)) { // \x10 comes first
+ var offset = offset1;
+ } else if(offset2 != -1) { // \x11 comes first
+ var offset = offset2;
+ } else { // both must be -1; no tags here
+ return [styleData.replace("\xFB", "", "g")];
+ }
+ // want to start with tag before
+ offset--;
+ // for the \x10\x10 case
+ if(offset === -1) offset = 0;
+
+ if(offset !== 0) {
+ fields.push(styleData.substr(0, offset).replace("\xFB", "", "g"));
+ }
+
+ while(offset < styleData.length) {
+ if((styleData[offset] == "\x10" || styleData[offset] == "\x11" || styleData[offset] == "\x12")
+ && styleData[offset+1] == "\x00" && styleData[offset+2] == "\x03") {
+ // 10 00 02 style short tag (use unknown)
+
+ fields.push({dle:styleData[offset],
+ type:"\x00",
+ flags:styleData[offset+3],
+ data:styleData.substr(offset+4, 4)});
+
+ offset += 8;
+ } else if(styleData[offset+2] == "\x01" || styleData[offset+2] == "\x02") {
+ // standard data-bearing tag
+
+ // size is little endian
+ var size = this.parseInt(styleData.substr(offset+4, 4));
+ size += size % 4;
+
+ // set field data
+ var field = {code:styleData[offset],
+ dle:styleData[offset+1],
+ type:styleData[offset+2],
+ flags:styleData[offset+3],
+ size:size,
+ data:styleData.substr(offset+8, size-8)};
+ field.subfields = this.parseFormat(field.data);
+ fields.push(field);
+
+ offset += size;
+ } else if(styleData[offset+2] == "\x03" || styleData[offset+2] == "\x00") {
+ // 10 03 style short tag (use unknown)
+
+ fields.push({code:styleData[offset],
+ dle:styleData[offset+1],
+ type:"\x03",
+ flags:styleData[offset+3],
+ data:styleData.substr(offset+4, 4)});
+
+ offset += 8;
+ } else if(styleData[offset+1] != "\x10" && styleData[offset+1] != "\x11") {
+ // unknown tag; error out
+ throw("Zotero.ENConverter: Unexpected end of file at "+offset.toString(16)+"; "+varDump(styleData.substr(offset, offset+4)));
+ }
+ }
+
+ return fields;
+}
+
+/**
+ * Finds all instances of a given field at a given level of the hierarchy
+ * @param {Array} fields The array of fields
+ * @param {String} code The field code
+ **/
+Zotero.ENConverter.prototype.findField = function(fields, code) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
+ var output = [];
+
+ while(code.length) {
+ if(typeof code != "object") {
+ var searchCode = code;
+ code = [];
+ } else {
+ var searchCode = code.shift();
+ }
+
+ for(var i=0; i tag
+ *
+ * @param {Object} options A binary field object
+ * @returns A tag
+ * @type XML
+ **/
+Zotero.ENConverter.prototype.parseName = function(options) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
+ var authorXML = ;
+
+ // "Author Lists" preferences
+ var delimiterOptions = this.findField(options.subfields, ["t", "x"]);
+ if(this.parseInt(this.findField(delimiterOptions[0].subfields, ["z"])[0].data) == 2) {
+ // this probably means delimiter-precedes-last shouldn't be set, because
+ // this is probably configured such that, from 1-2, we use no delimiter
+ // before the last, but for all other numbers of authors we do
+ var delimiter = this.parseFormattedString(this.findField(delimiterOptions[1].subfields, "{")[0].data);
+ var lastDelimiter = this.parseFormattedString(this.findField(delimiterOptions[1].subfields, "|")[0].data);
+ } else {
+ var delimiter = this.parseFormattedString(this.findField(delimiterOptions[0].subfields, "{")[0].data);
+ var lastDelimiter = this.parseFormattedString(this.findField(delimiterOptions[0].subfields, "|")[0].data);
+ // delimiter-precedes-last should probably be "always" or "never"
+ // ignore second set of list separator options
+ if(lastDelimiter.length >= delimiter.length
+ && lastDelimiter.substr(0, delimiter.length) == delimiter) {
+ // there is a delimiter preceding the last
+ authorXML["@delimiter-precedes-last"] = "always";
+ } else {
+ // there is no delimiter
+ authorXML["@delimiter-precedes-last"] = "never";
+ }
+ }
+ if(delimiter !== "") authorXML["@delimiter"] = delimiter;
+ // TODO: alter locale "and" if neither text nor symbol
+ if(lastDelimiter.indexOf("and") !== -1) {
+ // text and
+ authorXML["@and"] = "text";
+ } else if(lastDelimiter.indexOf("&") !== -1) {
+ // symbol and
+ authorXML["@and"] = "symbol";
+ }
+
+ // "Author Name" preferences
+ var firstAuthorPref = this.findField(options.subfields, "q")[0].data[0];
+ var subsequentAuthorPref = this.findField(options.subfields, "r")[0].data[0];
+ if(firstAuthorPref != "\x00") {
+ if(subsequentAuthorPref != "\x00") {
+ authorXML["@name-as-sort-order"] = "all";
+ } else {
+ authorXML["@name-as-sort-order"] = "first";
+ }
+ }
+ if(firstAuthorPref == "\x01") {
+ authorXML["@sort-separator"] = ", ";
+ } else if(firstAuthorPref == "\x02") {
+ authorXML["@sort-separator"] = " ";
+ }
+
+ var capitalizationPref = this.findField(options.subfields, "s")[0].data[0];
+ if(capitalizationPref == "\x02") {
+ authorXML["@text-case"] = "uppercase";
+ } else if(capitalizationPref == "\x03") {
+ authorXML["@font-variant"] = "small-caps";
+ }
+
+ var initialPref = this.findField(options.subfields, "p")[0].data[0];
+ if(initialPref == "\x01") { // B. C.
+ authorXML["@initialize-with"] = ". ";
+ } else if(initialPref == "\x02") { // B.C.
+ authorXML["@initialize-with"] = ".";
+ } else if(initialPref == "\x03") { // B C
+ authorXML["@initialize-with"] = " ";
+ } else if(initialPref == "\x04") { // BC
+ authorXML["@initialize-with"] = "";
+ } else if(initialPref == "\x05") { // just last name
+ authorXML["@form"] = "short";
+ }
+
+ return authorXML;
+}
+
+/**
+ * Parses options pertaining to subsequent author handling
+ *
+ * @param {Object} etAlOptions A binary field object
+ * @param {XML} context The CSL context ( or tag)
+ * @param {Boolean} subsequent Whether this set of fields controls the behavior
+ * of subsequent references.
+ **/
+Zotero.ENConverter.prototype.parseEtAl = function(etAlOptions, context, subsequent) {
+ default xml namespace = "http://purl.org/net/xbiblio/csl"; with({});
+
+ if(this.findField(etAlOptions.subfields, "}")[0].data[0] == "\x01") {
+ // if author list abbreviation is on
+
+ // et-al-min
+ var value = this.parseInt(this.findField(etAlOptions.subfields, "~")[0].data);
+ var optionName = subsequent ? "et-al-subsequent-min" : "et-al-min";
+ context.prependChild(