Commits

Dan Hagon committed 95116e4

Initial check in of CSL example from the citeproc-js examples.

  • Participants

Comments (0)

Files changed (12)

+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>schtml-citations</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+	</buildSpec>
+	<natures>
+	</natures>
+</projectDescription>

File article.html

+<!DOCTYPE HTML>
+<html xmlns:cito="http://purl.org/spar/cito/" xmlns:bibo="http://purl.org/ontology/bibo/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:dc="http://purl.org/dc/terms/" xmlns="http://www.w3.org/1999/xhtml" version="HTML+RDFa 1.0" lang="en">
+
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+
+	<script type="text/javascript" src="demo_files/loadabbrevs.js"></script>
+    <script type="text/javascript; e4x=1" src="demo_files/xmle4x.js"></script> 
+	<script type="text/javascript" src="demo_files/xmldom.js"></script>
+	<script type="text/javascript" src="demo_files/citeproc.js"></script>
+	<script type="text/javascript" src="demo_files/loadlocale.js"></script>
+	<script type="text/javascript" src="demo_files/loadsys.js"></script>
+	<script type="text/javascript" src="demo_files/loadcsl.js"></script>
+	<script type="text/javascript" src="demo_files/loadcites.js"></script>
+	<script type="text/javascript" src="demo_files/runcites.js"></script>
+
+<title>Article Demo</title>
+</head>
+
+
+<body onload="insert2()">
+<div id="article" about="http://example.com/schtml/article.html">
+
+    <h1 property="dc:title">My Really Interesting Article</h1>
+    <h2 rel="dc:creator" resource="http://people.cam.ac.uk/sea36">
+        <span property="foaf:name">Sam Adams</span>
+    </h2>
+
+    <p>This article cites
+        <a rel="cito:cites" resource="http://dx.doi.org/10.1039/B411699M" href="#cite1">
+            another really good paper
+        </a>!
+    </p>
+
+    <p>This article also cites
+        <a rel="cito:parodies" href="http://dx.doi.org/10.1021/cr900368a">
+            this paper
+        </a>.
+    </p>
+
+    <p>Here is a citation to
+        <a rel="cito:cites" resource="http://dx.doi.org/10.1038/nchem.402" href="#cite2">
+            another paper
+        </a>.
+    </p>
+
+
+    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis 
+sapien est, tincidunt volutpat molestie a, rutrum id augue. Nulla ornare
+ interdum massa, id viverra quam pretium eget. Nulla sed ipsum quam. 
+Nunc eu bibendum nisl. Quisque vehicula lectus leo. Donec erat libero, 
+ullamcorper vel condimentum non, ornare sodales dolor. Pellentesque a 
+sapien id odio accumsan hendrerit. Quisque hendrerit sapien sit amet 
+erat tincidunt sagittis. Maecenas suscipit mauris tristique nibh 
+pharetra condimentum. <span id="cad1"
+       name="citation_cad">[cite]</span> 
+Vivamus non ligula orci. Proin accumsan lectus 
+eget purus ultrices posuere.</p>
+
+    <p>In at elit ligula. Phasellus lobortis adipiscing leo, eget 
+bibendum purus congue quis. Duis sed dui rutrum augue pulvinar 
+venenatis. Morbi quam quam, elementum non porttitor sit amet, viverra 
+auctor velit. Suspendisse potenti. Nam eleifend semper mauris euismod 
+mattis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam 
+bibendum egestas tortor, non posuere leo accumsan ut. Curabitur at lacus
+ eu tortor rutrum tempor. <span id="cad2"
+       name="citation_cad">[cite]</span>
+ Phasellus venenatis viverra ligula eget 
+viverra. In pretium libero a libero malesuada ultrices. Cras consequat 
+sagittis justo eu congue. Vivamus lectus turpis, porta sit amet 
+condimentum et, adipiscing et urna.</p>
+
+    <p>Aliquam erat volutpat. Vivamus pharetra mollis pulvinar. Cum 
+sociis natoque penatibus et magnis dis parturient montes, nascetur 
+ridiculus mus. In nisi nisi, laoreet et viverra nec, venenatis vitae 
+urna. Nam placerat varius tincidunt. Vestibulum at tortor eu sapien 
+pretium commodo. Etiam mi erat, rhoncus et vestibulum non, gravida at 
+lacus. Maecenas sit amet risus lorem, vitae ullamcorper ante. 
+Pellentesque nulla nunc, ornare at gravida nec, tempor semper mauris. 
+Duis rutrum semper blandit. Maecenas in ultricies velit. Integer laoreet
+ pretium est, vel luctus elit feugiat in. Vestibulum est felis, iaculis 
+tempus ullamcorper sed, sodales a urna. Donec dui lectus, venenatis quis
+ venenatis at, sagittis in felis. Donec varius interdum placerat. 
+Maecenas ac velit a ligula congue fermentum quis non tellus. Aenean nec 
+mi quis diam eleifend pharetra vitae eget velit. Sed hendrerit nisi sit 
+amet risus rutrum mollis auctor enim sagittis. Praesent eleifend mi 
+ipsum.</p>
+
+    <p>Quisque malesuada placerat nisi. Cras feugiat suscipit libero, 
+quis aliquet ligula scelerisque eget. Etiam at placerat ante. 
+Pellentesque at ipsum nibh. Pellentesque habitant morbi tristique 
+senectus et netus et malesuada fames ac turpis egestas. Phasellus nisi 
+neque, mattis at molestie pharetra, vehicula at neque. Nulla at nulla 
+sapien, eget vestibulum est. Donec in mauris id turpis tempus tincidunt.
+ Proin at lorem ac elit iaculis rutrum in porta nunc. Maecenas interdum 
+condimentum diam et iaculis. Etiam nec convallis mauris. Nunc ligula 
+nibh, lacinia a pharetra id, elementum a tortor. Aliquam quis velit 
+lacus, vel interdum purus. Maecenas in nibh vitae massa cursus gravida 
+sed sed sem. In eget erat ac urna fermentum suscipit quis vitae erat. 
+Nam euismod lectus in lacus lacinia blandit non vitae augue. Nunc 
+gravida tincidunt tempus. Proin vehicula libero et tortor tempor 
+sollicitudin nec pulvinar turpis. Cras fermentum velit eget dui molestie
+ convallis.</p>
+
+    <p>Sed nunc metus, feugiat a placerat molestie, luctus ac neque. 
+Quisque ac turpis eu leo hendrerit vulputate vel a turpis. Praesent sit 
+amet nibh elit. Vivamus vitae purus et ipsum imperdiet laoreet. 
+Pellentesque habitant morbi tristique senectus et netus et malesuada 
+fames ac turpis egestas. Nulla vel libero mi. Nam euismod ornare felis 
+at porttitor. Ut scelerisque imperdiet volutpat. Proin sagittis auctor 
+aliquet. Duis porttitor velit vitae nisl gravida eu rhoncus purus 
+varius. Quisque commodo aliquam suscipit. Cras varius rutrum sem eget 
+rhoncus. Integer bibendum tempus pharetra. Fusce justo enim, imperdiet 
+vitae ultrices ac, ornare vel augue. Mauris non lectus eget turpis 
+hendrerit rhoncus. Nam nec elit sed dolor faucibus dictum. Morbi iaculis
+ aliquet lacinia. Vivamus faucibus faucibus condimentum. Aenean at 
+volutpat velit. Vestibulum egestas, metus sed laoreet luctus, enim purus
+ commodo lorem, eu tristique risus sapien at lacus.</p>
+
+     <h2>References</h2>
+	<div class="hangindent" id="chicago_author_date"><!--
+
+        NOTE: The "hangindent" class is a shortcut hack used
+        to display this specific page, which uses a static
+        set of known styles.  Where styles can be dynamically
+        assigned, the webserver or application should define
+        a set of appropriate style classes, and provide them
+        to the target rendering engine along with the processor
+        output.  For guidance, see the relevant section of the
+        processor manual:
+
+          http://gsl-nagoya-u.net/http/pub/citeproc-doc.html#return-value
+
+        -->
+[Page generation failure.  The bibliography processor requires a browser with Javascript enabled.]</div>
+
+
+ 
+    <div id="biblography">
+
+        <div about="http://dx.doi.org/10.1039/B411699M">
+            <a name="cite1"></a>
+            <span property="dc:title">Experimental data checker: better information for organic chemists</span>
+            <br>
+            <span rel="dc:creator">
+                <span resource="http://people.cam.ac.uk/sea36">
+                    <span property="foaf:name" content="Samuel E. Adams">S. E. Adams</span>
+                </span>,
+                <span resource="http://people.cam.ac.uk/jmg">
+                    <span property="foaf:name">J. M. Goodman</span>
+                </span>,
+                <span resource="http://people.rsc.org/rkidd">
+                    <span property="foaf:name" content="Richard J. Kidd">R. J. Kidd</span>
+                </span>,
+                <span resource="http://people.rsc.org/amcnaught">
+                    <span property="foaf:name">A. D. McNaught</span>
+                </span>,
+                <span resource="http://people.cam.ac.uk/pmr">
+                    <span property="foaf:name">P. Murray-Rust</span>
+                </span>,
+                <span resource="http://people.cam.ac.uk/frn">
+                    <span property="foaf:name">F. R. Norton</span>
+                </span>,
+                <span resource="http://people.cam.ac.uk/jat">
+                    <span property="foaf:name">J. A. Townsend</span>
+                </span>,
+                <span resource="http://people.cam.ac.uk/caw">
+                    <span property="foaf:name">C. A. Waudby</span>
+                </span>.
+            </span>
+            <br>
+            <span rel="dc:isPartOf" resource="[_:journal]">
+                <span property="dc:title" content="Organic &amp; Biomolecular Chemistry"></span>
+                <span property="bibo:shortTitle">Org. Biomol. Chem.</span>
+            </span>
+            <span property="dc:date">2004</span>,
+            <span property="bibo:volume">2</span>
+            (<span property="bibo:issue">21</span>),
+            <span property="bibo:pageStart">3067</span>-<span property="bibo:pageEnd">3070</span>
+            <br>
+            DOI: <a href="http://dx.doi.org/10.1039/B411699M" property="bibo:doi">10.1039/B411699M</a>
+        </div>
+
+        <br>
+
+        <div about="http://dx.doi.org/10.1038/nchem.402">
+            <a name="cite2"></a>
+            <span property="dc:title">Anhydrous proton conduction at 150&nbsp;°C in a crystalline metal–organic framework</span>
+            <br>
+            <span>
+                <span property="dc:creator">Jeff A. Hurd</span>
+                <span property="dc:creator">Ramanathan Vaidhyanathan</span>
+                <span property="dc:creator">Venkataraman Thangadurai</span>
+                <span property="dc:creator">Christopher I. Ratcliffe</span>
+                <span property="dc:creator">Igor L. Moudrakovski</span>
+                <span property="dc:creator">George K. H. Shimizu</span>
+            </span>
+            <br>
+            <span rel="dc:isPartOf" resource="[_:journal1]">
+                <span property="dc:title">Nature Chemistry</span>
+            </span>
+            <span property="dc:date">2009</span>,
+            <span property="bibo:volume">1</span>
+            (<span property="bibo:issue">9</span>),
+            <span property="bibo:pageStart">705</span>-<span property="bibo:pageEnd">710</span>
+            <br>
+            DOI: <a href="http://dx.doi.org/10.1038/nchem.402" property="bibo:doi">10.1038/nchem.402</a>
+        </div>
+
+    </div>
+
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+
+</div>
+</body></html>

File demo_files/citeproc.js

+if (!Array.indexOf) {
+	Array.prototype.indexOf = function (obj) {
+		var i, len;
+		for (i = 0, len = this.length; i < len; i += 1) {
+			if (this[i] === obj) {
+				return i;
+			}
+		}
+		return -1;
+	};
+}
+var CSL = {
+	GENDERS: ["masculine", "feminine"],
+	ERROR_NO_RENDERED_FORM: 1,
+	PREVIEW: "Just for laughs.",
+	ASSUME_ALL_ITEMS_REGISTERED: 2,
+	START: 0,
+	END: 1,
+	SINGLETON: 2,
+	SEEN: 6,
+	SUCCESSOR: 3,
+	SUCCESSOR_OF_SUCCESSOR: 4,
+	SUPPRESS: 5,
+	SINGULAR: 0,
+	PLURAL: 1,
+	LITERAL: true,
+	BEFORE: 1,
+	AFTER: 2,
+	DESCENDING: 1,
+	ASCENDING: 2,
+	ONLY_FIRST: 1,
+	ALWAYS: 2,
+	ONLY_LAST: 3,
+	FINISH: 1,
+	POSITION_FIRST: 0,
+	POSITION_SUBSEQUENT: 1,
+	POSITION_IBID: 2,
+	POSITION_IBID_WITH_LOCATOR: 3,
+	MARK_TRAILING_NAMES: true,
+	POSITION_TEST_VARS: ["position", "first-reference-note-number", "near-note"],
+	AREAS: ["citation", "citation_sort", "bibliography", "bibliography_sort"],
+	MULTI_FIELDS: ["publisher", "publisher-place", "title","container-title", "collection-title", "institution", "authority","edition"],
+	CITE_FIELDS: ["first-reference-note-number", "locator"],
+	MINIMAL_NAME_FIELDS: ["literal", "family"],
+	SWAPPING_PUNCTUATION: [".", "!", "?", ":",",",";"],
+	TERMINAL_PUNCTUATION: [".", "!", "?", ":", " "],
+	SPLICE_PUNCTUATION: [".", "!", "?", ":", ";", ","],
+	NONE: 0,
+	NUMERIC: 1,
+	POSITION: 2,
+	COLLAPSE_VALUES: ["citation-number", "year", "year-suffix"],
+	DATE_PARTS: ["year", "month", "day"],
+	DATE_PARTS_ALL: ["year", "month", "day", "season"],
+	DATE_PARTS_INTERNAL: ["year", "month", "day", "year_end", "month_end", "day_end"],
+	NAME_PARTS: ["family", "given", "dropping-particle", "non-dropping-particle", "suffix", "literal"],
+	DECORABLE_NAME_PARTS: ["given", "family", "suffix"],
+	DISAMBIGUATE_OPTIONS: [
+		"disambiguate-add-names",
+		"disambiguate-add-givenname",
+		"disambiguate-add-year-suffix"
+	],
+	GIVENNAME_DISAMBIGUATION_RULES: [
+		"all-names",
+		"all-names-with-initials",
+		"primary-name",
+		"primary-name-with-initials",
+		"by-cite"
+	],
+	NAME_ATTRIBUTES: [
+		"and",
+		"delimiter-precedes-last",
+		"delimiter-precedes-et-al",
+		"initialize-with",
+		"name-as-sort-order",
+		"sort-separator",
+		"et-al-min",
+		"et-al-use-first",
+		"et-al-subsequent-min",
+		"et-al-subsequent-use-first"
+	],
+	PARALLEL_MATCH_VARS: ["container-title"],
+	PARALLEL_TYPES: ["legal_case",  "legislation"],
+	PARALLEL_COLLAPSING_MID_VARSET: ["volume", "container-title", "section"],
+	LOOSE: 0,
+	STRICT: 1,
+	PREFIX_PUNCTUATION: /[.;:]\s*$/,
+	SUFFIX_PUNCTUATION: /^\s*[.;:,\(\)]/,
+	NUMBER_REGEXP: /(?:^\d+|\d+$)/,
+	QUOTED_REGEXP_START: /^"/,
+	QUOTED_REGEXP_END: /^"$/,
+	NAME_INITIAL_REGEXP: /^([A-Z\u0080-\u017f\u0400-\u042f])([a-zA-Z\u0080-\u017f\u0400-\u052f]*|)/,
+	ROMANESQUE_REGEXP: /[a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]/,
+	STARTSWITH_ROMANESQUE_REGEXP: /^[&a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]/,
+	ENDSWITH_ROMANESQUE_REGEXP: /[&a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]$/,
+	ALL_ROMANESQUE_REGEXP: /^[a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]+$/,
+	VIETNAMESE_SPECIALS: /[\u00c0-\u00c3\u00c8-\u00ca\u00cc\u00cd\u00d2-\u00d5\u00d9\u00da\u00dd\u00e0-\u00e3\u00e8-\u00ea\u00ec\u00ed\u00f2-\u00f5\u00f9\u00fa\u00fd\u0101\u0103\u0110\u0111\u0128\u0129\u0168\u0169\u01a0\u01a1\u01af\u01b0\u1ea0-\u1ef9]/,
+	VIETNAMESE_NAMES: /^(?:(?:[.AaBbCcDdEeGgHhIiKkLlMmNnOoPpQqRrSsTtUuVvXxYy \u00c0-\u00c3\u00c8-\u00ca\u00cc\u00cd\u00d2-\u00d5\u00d9\u00da\u00dd\u00e0-\u00e3\u00e8-\u00ea\u00ec\u00ed\u00f2-\u00f5\u00f9\u00fa\u00fd\u0101\u0103\u0110\u0111\u0128\u0129\u0168\u0169\u01a0\u01a1\u01af\u01b0\u1ea0-\u1ef9]{2,6})(\s+|$))+$/,
+	NOTE_FIELDS_REGEXP: /{:[-a-z]+:[^}]+}/g,
+	NOTE_FIELD_REGEXP: /{:([-a-z]+):([^}]+)}/,
+	DISPLAY_CLASSES: ["block", "left-margin", "right-inline", "indent"],
+	NAME_VARIABLES: [
+		"author",
+		"editor",
+		"translator",
+		"contributor",
+		"collection-editor",
+		"composer",
+		"container-author",
+		"editorial-director",
+		"interviewer",
+		"original-author",
+		"recipient"
+	],
+	NUMERIC_VARIABLES: ["edition", "volume", "number-of-volumes", "number", "issue", "citation-number"],
+	DATE_VARIABLES: ["issued", "event-date", "accessed", "container", "original-date"],
+	TAG_ESCAPE: function (str) {
+		var mx, lst, len, pos, m, buf1, buf2, idx, ret, myret;
+		mx = str.match(/(<span\s+class=\"no(?:case|decor)\">)/g);
+		lst = str.split(/<span\s+class=\"no(?:case|decor)\">/g);
+		myret = [lst[0]];
+		for (pos = 1, len = lst.length; pos < len; pos += 1) {
+			myret.push(mx[pos - 1]);
+			myret.push(lst[pos]);
+		}
+		lst = myret.slice();
+		len = lst.length - 1;
+		for (pos = len; pos > 1; pos += -2) {
+			m = lst[pos].match(/<\/span>/);
+			if (m) {
+				idx = lst[pos].indexOf("</span>");
+				buf1 = lst[pos].slice(0, idx);
+				buf2 = lst[pos].slice(idx + 7);
+				lst[pos - 1] += buf1 + "</span>";
+				lst[pos] = buf2;
+			} else {
+				buf1 = lst.slice(0, pos - 1);
+				if (pos < (lst.length - 1)) {
+					buf2 = lst[pos - 1] + lst[pos];
+				} else {
+					buf2 = lst[pos - 1] + lst[pos] + lst[pos + 1];
+				}
+				lst = buf1.push(buf2).concat(lst.slice(pos + 2));
+			}
+		}
+		return lst;
+	},
+	TAG_USEALL: function (str) {
+		var ret, open, close, end;
+		ret = [""];
+		open = str.indexOf("<");
+		close = str.indexOf(">");
+		while (open > -1 && close > -1) {
+			if (open > close) {
+				end = open + 1;
+			} else {
+				end = close + 1;
+			}
+			if (open < close && str.slice(open + 1, close).indexOf("<") === -1) {
+				ret[ret.length - 1] += str.slice(0, open);
+				ret.push(str.slice(open, close + 1));
+				ret.push("");
+				str = str.slice(end);
+			} else {
+				ret[ret.length - 1] += str.slice(0, close + 1);
+				str = str.slice(end);
+			}
+			open = str.indexOf("<");
+			close = str.indexOf(">");
+		}
+		ret[ret.length - 1] += str;
+		return ret;
+	},
+	SKIP_WORDS: ["a", "the", "an"],
+	FORMAT_KEY_SEQUENCE: [
+		"@strip-periods",
+		"@font-style",
+		"@font-variant",
+		"@font-weight",
+		"@text-decoration",
+		"@vertical-align",
+		"@quotes"
+	],
+	INSTITUTION_KEYS: [
+		"font-style",
+		"font-variant",
+		"font-weight",
+		"text-decoration"
+	],
+	SUFFIX_CHARS: "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z",
+	ROMAN_NUMERALS: [
+		[ "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" ],
+		[ "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" ],
+		[ "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" ],
+		[ "", "m", "mm", "mmm", "mmmm", "mmmmm"]
+	],
+	CREATORS: [
+		"author",
+		"editor",
+		"contributor",
+		"translator",
+		"recipient",
+		"interviewer",
+		"composer",
+		"original-author",
+		"container-author",
+		"collection-editor"
+	],
+	LANG_BASES: {
+		af: "af_ZA",
+		ar: "ar_AR",
+		bg: "bg_BG",
+		ca: "ca_AD",
+		cs: "cs_CZ",
+		da: "da_DK",
+		de: "de_DE",
+		el: "el_GR",
+		en: "en_US",
+		es: "es_ES",
+		et: "et_EE",
+		fr: "fr_FR",
+		he: "he_IL",
+		hu: "hu_HU",
+		is: "is_IS",
+		it: "it_IT",
+		ja: "ja_JP",
+		km: "km_KH",
+		ko: "ko_KR",
+		mn: "mn_MN",
+		nb: "nb_NO",
+		nl: "nl_NL",
+		pl: "pl_PL",
+		pt: "pt_PT",
+		ro: "ro_RO",
+		ru: "ru_RU",
+		sk: "sk_SK",
+		sl: "sl_SI",
+		sr: "sr_RS",
+		sv: "sv_SE",
+		th: "th_TH",
+		tr: "tr_TR",
+		uk: "uk_UA",
+		vi: "vi_VN",
+		zh: "zh_CN"
+	},
+	locale: {},
+	locale_opts: {},
+	locale_dates: {}
+};
+CSL.TERMINAL_PUNCTUATION_REGEXP = new RegExp("^([" + CSL.TERMINAL_PUNCTUATION.slice(0, -1).join("") + "])(.*)");
+CSL.CLOSURES = new RegExp(".*[\\]\\)]");
+if ("object" === typeof console && "function" === typeof console.log) {
+	CSL.debug = function (str) {
+        console.log("CSL: " + str);
+	};
+	CSL.error = function (str) {
+        console.log("CSL error: " + str);
+	};
+} else {
+	CSL.debug = function () {};
+	CSL.error = function (str) {
+		throw "CSL error: " + str;
+	};
+}
+CSL.Output = {};
+CSL.Output.Queue = function (state) {
+	this.levelname = ["top"];
+	this.state = state;
+	this.queue = [];
+	this.empty = new CSL.Token("empty");
+	var tokenstore = {};
+	tokenstore.empty = this.empty;
+	this.formats = new CSL.Stack(tokenstore);
+	this.current = new CSL.Stack(this.queue);
+};
+CSL.Output.Queue.prototype.getToken = function (name) {
+	var ret = this.formats.value()[name];
+	return ret;
+};
+CSL.Output.Queue.prototype.mergeTokenStrings = function (base, modifier) {
+	var base_token, modifier_token, ret, key;
+	base_token = this.formats.value()[base];
+	modifier_token = this.formats.value()[modifier];
+	ret = base_token;
+	if (modifier_token) {
+		if (!base_token) {
+			base_token = new CSL.Token(base, CSL.SINGLETON);
+			base_token.decorations = [];
+		}
+		ret = new CSL.Token(base, CSL.SINGLETON);
+		key = "";
+		for (key in base_token.strings) {
+			if (base_token.strings.hasOwnProperty(key)) {
+				ret.strings[key] = base_token.strings[key];
+			}
+		}
+		for (key in modifier_token.strings) {
+			if (modifier_token.strings.hasOwnProperty(key)) {
+				ret.strings[key] = modifier_token.strings[key];
+			}
+		}
+		ret.decorations = base_token.decorations.concat(modifier_token.decorations);
+	}
+	return ret;
+};
+CSL.Output.Queue.prototype.addToken = function (name, modifier, token) {
+	var newtok, attr;
+	newtok = new CSL.Token("output");
+	if ("string" === typeof token) {
+		token = this.formats.value()[token];
+	}
+	if (token && token.strings) {
+		for (attr in token.strings) {
+			if (token.strings.hasOwnProperty(attr)) {
+				newtok.strings[attr] = token.strings[attr];
+			}
+		}
+		newtok.decorations = token.decorations;
+	}
+	if ("string" === typeof modifier) {
+		newtok.strings.delimiter = modifier;
+	}
+	this.formats.value()[name] = newtok;
+};
+CSL.Output.Queue.prototype.pushFormats = function (tokenstore) {
+	if (!tokenstore) {
+		tokenstore = {};
+	}
+	tokenstore.empty = this.empty;
+	this.formats.push(tokenstore);
+};
+CSL.Output.Queue.prototype.popFormats = function (tokenstore) {
+	this.formats.pop();
+};
+CSL.Output.Queue.prototype.startTag = function (name, token) {
+	var tokenstore = {};
+	tokenstore[name] = token;
+	this.pushFormats(tokenstore);
+	this.openLevel(name);
+};
+CSL.Output.Queue.prototype.endTag = function () {
+	this.closeLevel();
+	this.popFormats();
+};
+CSL.Output.Queue.prototype.openLevel = function (token, ephemeral) {
+	var blob, curr, x, has_ephemeral;
+	if (!this.formats.value()[token]) {
+		throw "CSL processor error: call to nonexistent format token \"" + token + "\"";
+	}
+	blob = new CSL.Blob(this.formats.value()[token], false, token);
+	if (this.state.tmp.count_offset_characters && blob.strings.prefix.length) {
+		this.state.tmp.offset_characters += blob.strings.prefix.length;
+	}
+	if (this.state.tmp.count_offset_characters && blob.strings.suffix.length) {
+		this.state.tmp.offset_characters += blob.strings.suffix.length;
+	}
+	curr = this.current.value();
+	has_ephemeral = false;
+	for (x in this.state.tmp.names_cut.variable) {
+		if (this.state.tmp.names_cut.variable.hasOwnProperty(x)) {
+			has_ephemeral = x;
+			break;
+		}
+	}
+	if (ephemeral && (!has_ephemeral || ephemeral === has_ephemeral)) {
+		if (!this.state.tmp.names_cut.variable[ephemeral]) {
+			this.state.tmp.names_cut.variable[ephemeral] = [];
+			this.state.tmp.names_cut.used = ephemeral;
+		}
+		this.state.tmp.names_cut.variable[ephemeral].push([curr, curr.blobs.length]);
+	}
+	curr.push(blob);
+	this.current.push(blob);
+};
+CSL.Output.Queue.prototype.closeLevel = function (name) {
+	if (name && name !== this.current.value().levelname) {
+		CSL.error("Level mismatch error:  wanted " + name + " but found " + this.current.value().levelname);
+	}
+	this.current.pop();
+};
+CSL.Output.Queue.prototype.append = function (str, tokname) {
+	var token, blob, curr;
+	if ("undefined" === typeof str) {
+		return;
+	}
+	if ("number" === typeof str) {
+		str = "" + str;
+	}
+	if (this.state.tmp.element_trace && this.state.tmp.element_trace.value() === "suppress-me") {
+		return;
+	}
+	blob = false;
+	if (!tokname) {
+		token = this.formats.value().empty;
+	} else if (tokname === "literal") {
+		token = true;
+	} else if ("string" === typeof tokname) {
+		token = this.formats.value()[tokname];
+	} else {
+		token = tokname;
+	}
+	if (!token) {
+		throw "CSL processor error: unknown format token name: " + tokname;
+	}
+	if ("string" === typeof str && str.length) {
+		this.last_char_rendered = str.slice(-1);
+		str = str.replace(/\s+'/g, "  \'").replace(/^'/g, " \'");
+		this.state.tmp.term_predecessor = true;
+	}
+	blob = new CSL.Blob(token, str);
+	if (this.state.tmp.count_offset_characters && blob.strings.prefix) {
+		this.state.tmp.offset_characters += blob.strings.prefix.length;
+	}
+	if (this.state.tmp.count_offset_characters && blob.strings.suffix) {
+		this.state.tmp.offset_characters += blob.strings.suffix.length;
+	}
+	curr = this.current.value();
+	if ("string" === typeof blob.blobs) {
+		this.state.tmp.term_predecessor = true;
+	}
+	if (this.state.tmp.count_offset_characters) {
+		if ("string" === typeof str) {
+			this.state.tmp.offset_characters += blob.strings.prefix.length;
+			this.state.tmp.offset_characters += blob.strings.suffix.length;
+			this.state.tmp.offset_characters += blob.blobs.length;
+		} else if ("undefined" !== str.num) {
+			this.state.tmp.offset_characters += str.strings.prefix.length;
+			this.state.tmp.offset_characters += str.strings.suffix.length;
+			this.state.tmp.offset_characters += str.formatter.format(str.num).length;
+		}
+	}
+	this.state.parallel.AppendBlobPointer(curr);
+	if ("string" === typeof str) {
+		curr.push(blob);
+		if (blob.strings["text-case"]) {
+			blob.blobs = CSL.Output.Formatters[blob.strings["text-case"]](this.state, str);
+		}
+		this.state.fun.flipflopper.init(str, blob);
+		this.state.fun.flipflopper.processTags();
+	} else {
+		curr.push(str);
+	}
+};
+CSL.Output.Queue.prototype.string = function (state, myblobs, blob) {
+	var blobs, ret, blob_delimiter, i, params, blobjr, last_str, last_char, b, use_suffix, qres, addtoret, span_split, j, res, blobs_start, blobs_end, key, pos, len, ppos, llen, ttype, ltype, terminal, leading, delimiters, use_prefix, txt_esc;
+	txt_esc = CSL.Output.Formats[this.state.opt.mode].text_escape;
+	blobs = myblobs.slice();
+	ret = [];
+	if (blobs.length === 0) {
+		return ret;
+	}
+	if (!blob) {
+		blob_delimiter = "";
+	} else {
+		blob_delimiter = blob.strings.delimiter;
+	}
+	if (blob && blob.new_locale) {
+		state.opt.lang = blob.new_locale;
+	}
+	for (pos = 0, len = blobs.length; pos < len; pos += 1) {
+		blobjr = blobs[pos];
+		if ("string" === typeof blobjr.blobs) {
+			if ("number" === typeof blobjr.num) {
+				ret.push(blobjr);
+			} else if (blobjr.blobs) {
+				b = blobjr.blobs;
+				use_suffix = blobjr.strings.suffix;
+				use_prefix = blobjr.strings.prefix;
+				if (!state.tmp.suppress_decorations) {
+					llen = blobjr.decorations.length;
+					for (ppos = 0; ppos < llen; ppos += 1) {
+						params = blobjr.decorations[ppos];
+						b = state.fun.decorate[params[0]][params[1]](state, b);
+					}
+				}
+				if (b && b.length) {
+					b = txt_esc(blobjr.strings.prefix) + b + txt_esc(use_suffix);
+					ret.push(b);
+				}
+			}
+		} else if (blobjr.blobs.length) {
+			addtoret = state.output.string(state, blobjr.blobs, blobjr);
+			if (ret.slice(-1)[0] && addtoret.slice(-1)[0]) {
+				ttype = typeof ret.slice(-1)[0];
+				ltype = typeof addtoret.slice(-1)[0];
+				if ("string" === ttype && "string" === ltype) {
+					terminal = ret.slice(-1)[0].slice(-1);
+					leading = addtoret.slice(-1)[0].slice(0, 1);
+				}
+			}
+			ret = ret.concat(addtoret);
+		} else {
+			continue;
+		}
+	}
+	span_split = 0;
+	len = ret.length;
+	for (pos = 0; pos < len; pos += 1) {
+		if ("string" === typeof ret[pos]) {
+			span_split = (parseInt(pos, 10) + 1);
+		}
+	}
+	if (blob && (blob.decorations.length || blob.strings.suffix || blob.strings.prefix)) {
+		span_split = ret.length;
+	}
+	blobs_start = state.output.renderBlobs(ret.slice(0, span_split), blob_delimiter);
+	if (blobs_start && blob && (blob.decorations.length || blob.strings.suffix || blob.strings.prefix)) {
+		if (!state.tmp.suppress_decorations) {
+			len = blob.decorations.length;
+			for (pos = 0; pos < len; pos += 1) {
+				params = blob.decorations[pos];
+				if (["@bibliography", "@display"].indexOf(params[0]) > -1) {
+					continue;
+				}
+				blobs_start = state.fun.decorate[params[0]][params[1]](state, blobs_start);
+			}
+		}
+		b = blobs_start;
+		use_suffix = blob.strings.suffix;
+		if (b && b.length) {
+			use_prefix = blob.strings.prefix;
+			b = txt_esc(use_prefix) + b + txt_esc(use_suffix);
+		}
+		blobs_start = b;
+		if (!state.tmp.suppress_decorations) {
+			len = blob.decorations.length;
+			for (pos = 0; pos < len; pos += 1) {
+				params = blob.decorations[pos];
+				if (["@bibliography", "@display"].indexOf(params[0]) === -1) {
+					continue;
+				}
+				blobs_start = state.fun.decorate[params[0]][params[1]](state, blobs_start);
+			}
+		}
+	}
+	blobs_end = ret.slice(span_split, ret.length);
+	if (!blobs_end.length && blobs_start) {
+		ret = [blobs_start];
+	} else if (blobs_end.length && !blobs_start) {
+		ret = blobs_end;
+	} else if (blobs_start && blobs_end.length) {
+		ret = [blobs_start].concat(blobs_end);
+	}
+	if ("undefined" === typeof blob) {
+		this.queue = [];
+		this.current.mystack = [];
+		this.current.mystack.push(this.queue);
+		if (state.tmp.suppress_decorations) {
+			ret = state.output.renderBlobs(ret);
+		}
+	} else if ("boolean" === typeof blob) {
+		ret = state.output.renderBlobs(ret);
+	}
+	if (blob && blob.new_locale) {
+		state.opt.lang = blob.old_locale;
+	}
+	if (blob) {
+		return ret;
+	} else {
+		return ret;
+	}
+};
+CSL.Output.Queue.prototype.clearlevel = function () {
+	var blob, pos, len;
+	blob = this.current.value();
+	len = blob.blobs.length;
+	for (pos = 0; pos < len; pos += 1) {
+		blob.blobs.pop();
+	}
+};
+CSL.Output.Queue.prototype.renderBlobs = function (blobs, delim) {
+	var state, ret, ret_last_char, use_delim, i, blob, pos, len, ppos, llen, pppos, lllen, res, str, params, txt_esc;
+	txt_esc = CSL.Output.Formats[this.state.opt.mode].text_escape;
+	if (!delim) {
+		delim = "";
+	}
+	state = this.state;
+	ret = "";
+	ret_last_char = [];
+	use_delim = "";
+	len = blobs.length;
+	for (pos = 0; pos < len; pos += 1) {
+		if (blobs[pos].checkNext) {
+			blobs[pos].checkNext(blobs[(pos + 1)]);
+		}
+	}
+	var doit = true;
+	for (pos = blobs.length - 1; pos > 0; pos += -1) {
+	    if (blobs[pos].checkLast) {
+		if (doit && blobs[pos].checkLast(blobs[pos - 1])) {
+		    doit = false;
+		}
+	    } else {
+		doit = true;
+	    }
+	}
+	len = blobs.length;
+	for (pos = 0; pos < len; pos += 1) {
+		blob = blobs[pos];
+		if (ret) {
+			use_delim = delim;
+		}
+		if (blob && "string" === typeof blob) {
+			ret += txt_esc(use_delim);
+			ret += blob;
+		} else if (blob.status !== CSL.SUPPRESS) {
+			str = blob.formatter.format(blob.num, blob.gender);
+			if (blob.strings["text-case"]) {
+				str = CSL.Output.Formatters[blob.strings["text-case"]](this.state, str);
+			}
+			if (!state.tmp.suppress_decorations) {
+				llen = blob.decorations.length;
+				for (ppos = 0; ppos < llen; ppos += 1) {
+					params = blob.decorations[ppos];
+					str = state.fun.decorate[params[0]][params[1]](state, str);
+				}
+			}
+			str = blob.strings.prefix + str + blob.strings.suffix;
+			if (blob.status === CSL.END) {
+				ret += blob.range_prefix;
+			} else if (blob.status === CSL.SUCCESSOR) {
+				ret += blob.successor_prefix;
+			} else if (blob.status === CSL.START) {
+				ret += "";
+			} else if (blob.status === CSL.SEEN) {
+				ret += blob.splice_prefix;
+			}
+			ret += str;
+		}
+	}
+	return ret;
+};
+CSL.Output.Queue.purgeEmptyBlobs = function (myblobs, endOnly) {
+	var res, j, jlen, tmpblobs;
+	if ("string" === typeof myblobs || !myblobs.length) {
+		return;
+	}
+	for (var i = myblobs.length - 1; i > -1; i += -1) {
+		CSL.Output.Queue.purgeEmptyBlobs(myblobs[i].blobs);		
+	}
+	for (var i = myblobs.length - 1; i > -1; i += -1) {
+		if (!myblobs[i].blobs.length) {
+			tmpblobs = myblobs.slice(i + 1);
+			for (j = i, jlen = myblobs.length; j < jlen; j += 1) {
+				myblobs.pop();
+			}
+			for (j = 0, jlen = tmpblobs.length; j < jlen; j += 1) {
+				myblobs.push(tmpblobs[j]);
+			}
+		} else if (endOnly) {
+			break;
+		}
+	}
+}
+CSL.Output.Queue.purgeNearsidePrefixChars = function(myblob, chr) {
+	if (!chr) {
+		return;
+	}
+	if ("object" === typeof myblob) {
+		if ((CSL.TERMINAL_PUNCTUATION.indexOf(chr) > -1 && 
+			 CSL.TERMINAL_PUNCTUATION.slice(0, -1).indexOf(myblob.strings.prefix.slice(0, 1)) > -1)) {
+			myblob.strings.prefix = myblob.strings.prefix.slice(1);
+		} else if ("object" === typeof myblob.blobs) {
+			CSL.Output.Queue.purgeNearsidePrefixChars(myblob.blobs[0], chr);
+		}
+	}
+}
+CSL.Output.Queue.purgeNearsidePrefixSpaces = function(myblob, chr) {
+	if ("object" === typeof myblob) {
+		if (" " === chr && " " === myblob.strings.prefix.slice(0, 1)) {
+			myblob.strings.prefix = myblob.strings.prefix.slice(1);
+		} else if ("object" === typeof myblob.blobs) {
+			CSL.Output.Queue.purgeNearsidePrefixSpaces(myblob.blobs[0], chr);
+		}
+	}
+}
+CSL.Output.Queue.purgeNearsideSuffixSpaces = function(myblob, chr) {
+	if ("object" === typeof myblob) {
+		if (" " === chr && " " === myblob.strings.suffix.slice(-1)) {
+			myblob.strings.suffix = myblob.strings.suffix.slice(0, -1);
+		} else if ("object" === typeof myblob.blobs) {
+			if (!chr) {
+				chr = myblob.strings.suffix.slice(-1);
+			}
+			chr = CSL.Output.Queue.purgeNearsideSuffixSpaces(myblob.blobs[myblob.blobs.length - 1], chr);
+		} else {
+			chr = myblob.strings.suffix.slice(-1);
+		}
+	}
+	return chr;
+}
+CSL.Output.Queue.adjustPunctuation = function (state, myblobs, stk, finish) {
+	var chr, suffix, dpref, blob, delimiter, suffixX, dprefX, blobX, delimiterX, prefix, prefixX, dsuffX, dsuff, slast, dsufff, dsufffX, lastchr, firstchr, chr, exposed_suffixes, exposed;
+	var TERMS = CSL.TERMINAL_PUNCTUATION.slice(0, -1);
+	var TERM_OR_SPACE = CSL.TERMINAL_PUNCTUATION;
+	var SWAPS = CSL.SWAPPING_PUNCTUATION;
+	if (!stk) {
+		stk = [{suffix: "", delimiter: ""}];
+	}
+	slast = stk.length - 1;
+	delimiter = stk[slast].delimiter;
+	dpref = stk[slast].dpref;
+	dsuff = stk[slast].dsuff;
+	dsufff = stk[slast].dsufff;
+	prefix = stk[slast].prefix;
+	suffix = stk[slast].suffix;
+	blob = stk[slast].blob;
+	if ("string" === typeof myblobs) {
+		if (suffix) {
+			if (blob && 
+				TERMS.indexOf(myblobs.slice(-1)) > -1 &&
+				TERMS.indexOf(suffix) > -1) {
+					blob.strings.suffix = blob.strings.suffix.slice(1);
+			}
+		}
+		lastchr = myblobs.slice(-1);
+		firstchr = myblobs.slice(0,1);
+	} else {
+		if (dpref) {
+			for (var j = 0, jlen = myblobs.length - 1; j < jlen; j += 1) {
+				var t = myblobs[j].strings.suffix.slice(-1);
+				if (TERMS.indexOf(t) === -1 ||
+				    TERMS.indexOf(dpref) === -1) {
+					if (dpref !== " " || dpref !== myblobs[j].strings.suffix.slice(-1)) {
+						myblobs[j].strings.suffix += dpref;						
+					}
+				}
+			}
+		}
+		if (suffix === " ") {
+			CSL.Output.Queue.purgeNearsideSuffixSpaces(myblobs[myblobs.length - 1], " ");
+		}
+		var lst = [];
+		for (var i = 0, ilen = myblobs.length - 1; i < ilen; i += 1) {
+			var doblob = myblobs[i];
+			var following_prefix = myblobs[i + 1].strings.prefix;
+			var chr = false;
+			var ret = CSL.Output.Queue.purgeNearsideSuffixSpaces(doblob, chr);
+			if (!dsuff) {
+				lst.push(ret);
+			} else {
+				lst.push(false);
+			}
+		}
+		chr = false;
+		for (var i = 1, ilen = myblobs.length; i < ilen; i += 1) {
+			var doblob = myblobs[i];
+			var chr = "";
+			var preceding_suffix = myblobs[i - 1].strings.suffix;
+			if (dsuff === " ") {
+				chr = dsuff;
+			} else if (preceding_suffix) {
+				chr = preceding_suffix.slice(-1);
+			} else if (lst[i - 1]) {
+				chr = lst[i - 1];
+			}
+			CSL.Output.Queue.purgeNearsidePrefixSpaces(doblob, chr);
+		}
+		if (dsufff) {
+			CSL.Output.Queue.purgeNearsidePrefixSpaces(myblobs[0], " ");
+		} else if (prefix === " ") {
+			CSL.Output.Queue.purgeNearsidePrefixSpaces(myblobs[0], " ");
+		}
+		for (var i = 0, ilen = myblobs.length; i < ilen; i += 1) {
+			var doblob = myblobs[i];
+			CSL.Output.Queue.purgeNearsidePrefixChars(doblob, lastchr);
+			if (i === 0) {
+				if (prefix) {
+					if (doblob.strings.prefix.slice(0, 1) === " ") {
+					}
+				}
+			}
+			if (dsufff) {
+				if (doblob.strings.prefix) {
+					if (i === 0) {
+						if (doblob.strings.prefix.slice(0, 1) === " ") {
+						}
+					}
+				}
+			}
+			if (dsuff) {
+				if (i > 0) {
+					if (doblob.strings.prefix.slice(0, 1) === " ") {
+					}
+				}
+			}
+			if (i < (myblobs.length - 1)) {
+				var nextprefix = myblobs[i + 1].strings.prefix;
+				if (!delimiter) {
+					if (nextprefix) {
+						var nxtchr = nextprefix.slice(0, 1);
+						if (SWAPS.indexOf(nxtchr) > -1) {
+							myblobs[i + 1].strings.prefix = nextprefix.slice(1);
+							if (TERMS.indexOf(nxtchr) === -1 ||
+								(TERMS.indexOf(nxtchr) > -1 &&
+								 TERMS.indexOf(doblob.strings.suffix.slice(-1)) === -1)) {
+									 doblob.strings.suffix += nxtchr;
+							}
+						} else if (nxtchr === " " &&
+									doblob.strings.suffix.slice(-1) === " ") {
+							doblob.strings.suffix = doblob.strings.suffix.slice(0, -1);
+						}
+					}
+				}
+			}
+			if (i === (myblobs.length - 1)) {
+				if (suffix) {
+					if (doblob.strings.suffix && 
+						 (TERMS.indexOf(suffix) > -1 &&
+						  TERMS.indexOf(doblob.strings.suffix.slice(-1)) > -1)) {
+							blob.strings.suffix = blob.strings.suffix.slice(1);
+					}
+				}
+			}
+			if ("string" === typeof doblob.blobs && doblob.blobs) {
+				for (var ppos = doblob.decorations.length - 1; ppos > -1; ppos += -1) {
+					var params = doblob.decorations[ppos];
+					if (params[0] === "@strip-periods" && params[1] === "true") {
+						doblob.blobs = state.fun.decorate[params[0]][params[1]](state, doblob.blobs);
+						doblob.decorations = doblob.decorations.slice(0, ppos).concat(doblob.decorations.slice(ppos + 1));
+					}
+				}
+			}
+			if (state.getOpt('punctuation-in-quote')) {
+				var decorations = doblob.decorations;
+				for (var j = 0, jlen = decorations.length; j < jlen; j += 1) {
+					if (decorations[j][0] === '@quotes' && decorations[j][1] === 'true') {
+						var swapchar = doblob.strings.suffix.slice(0, 1);
+						var swapblob = false;
+						if (SWAPS.indexOf(swapchar) > -1) {
+							swapblob = doblob;
+						} else if (SWAPS.indexOf(suffix) > -1 && i === (myblobs.length - 1)) {
+							swapchar = suffix;
+							swapblob = blob;
+						} else {
+							swapchar = false;
+						}
+						if (swapchar) {
+							if ("string" === typeof doblob.blobs) {
+								if (SWAPS.indexOf(doblob.blobs.slice(-1)) === -1 ||
+								   (TERMS.indexOf(doblob.blobs.slice(-1)) > -1 &&
+									SWAPS.indexOf(swapchar) > -1 &&
+									TERMS.indexOf(swapchar) === -1)) {
+										doblob.blobs += swapchar;
+								}
+							} else {
+								if (SWAPS.indexOf(doblob.blobs.slice(-1)[0].strings.suffix.slice(-1)) === -1 ||
+									(TERMS.indexOf(doblob.blobs.slice(-1)[0].strings.suffix.slice(-1)) > -1 &&
+									 SWAPS.indexOf(swapchar) > -1 &&
+									 TERMS.indexOf(swapchar) === -1)) {
+										 doblob.blobs.slice(-1)[0].strings.suffix += swapchar;
+								}
+							}
+							swapblob.strings.suffix = swapblob.strings.suffix.slice(1);
+						}
+					}
+				}
+			}
+			if (i === (myblobs.length - 1)) {
+				if (doblob.strings.suffix) {
+					suffixX = doblob.strings.suffix.slice(0, 1);
+					blobX = doblob;
+				} else {
+					suffixX = stk[stk.length - 1].suffix;
+					blobX = stk[stk.length - 1].blob;
+				}
+			} else {
+				if (doblob.strings.suffix) {
+					suffixX = doblob.strings.suffix.slice(0, 1);
+					blobX = doblob;
+  				} else {
+					suffixX = "";
+					blobX = false;
+				}
+			}
+			if (SWAPS.concat([" "]).indexOf(suffixX) === -1) {
+				suffixX = "";
+				blobX = false;
+			}
+			if (doblob.strings.delimiter && 
+				doblob.blobs.length > 1) {
+				dprefX = doblob.strings.delimiter.slice(0, 1);
+				if (SWAPS.concat([" "]).indexOf(dprefX) > -1) {
+					doblob.strings.delimiter = doblob.strings.delimiter.slice(1);
+				} else {
+					dprefX = "";
+				}
+			} else {
+				dprefX = "";
+			}
+			if (doblob.strings.prefix) {
+				if (doblob.strings.prefix.slice(-1) === " ") {
+					prefixX = " ";
+				} else {
+					prefixX = "";
+				}
+			} else {
+				if (i === 0) {
+					prefixX = prefix;					
+				} else {
+					prefixX = "";
+				}
+			}
+			if (dsuff) {
+				dsufffX = dsuff;
+			} else {
+				if (i === 0) {
+					dsufffX = dsufff;					
+				} else {
+					dsufffX = "";
+				}
+			}
+			if (doblob.strings.delimiter) {
+				if (doblob.strings.delimiter.slice(-1) === " " &&
+					"object" === typeof doblob.blobs && doblob.blobs.length > 1) {
+					   dsuffX = doblob.strings.delimiter.slice(-1);
+				} else {
+					dsuffX = "";						
+				}
+			} else {
+				dsuffX = "";					
+			}
+			delimiterX = doblob.strings.delimiter;
+			stk.push({suffix: suffixX, dsuff:dsuffX, blob:blobX, delimiter:delimiterX, prefix:prefixX, dpref: dprefX, dsufff: dsufffX});
+			lastchr = CSL.Output.Queue.adjustPunctuation(state, doblob.blobs, stk);
+		}
+		if (myblobs && myblobs.length) {
+			var last_suffix = myblobs[myblobs.length - 1].strings.suffix;
+			if (last_suffix) {
+				lastchr = last_suffix.slice(-1);
+			}
+		}
+	}
+	if (stk.length > 1) {
+		stk.pop();
+	}
+	state.tmp.last_chr = lastchr;
+	return lastchr;
+};
+CSL.substituteOne = function (template) {
+	return function (state, list) {
+		if (!list) {
+			return "";
+		} else {
+			return template.replace("%%STRING%%", list);
+		}
+	};
+};
+CSL.substituteTwo = function (template) {
+	return function (param) {
+		var template2 = template.replace("%%PARAM%%", param);
+		return function (state, list) {
+			if (!list) {
+				return "";
+			} else {
+				return template2.replace("%%STRING%%", list);
+			}
+		};
+	};
+};
+CSL.Mode = function (mode) {
+	var decorations, params, param, func, val, args;
+	decorations = {};
+	params = CSL.Output.Formats[mode];
+	for (param in params) {
+		if (true) {
+			if ("@" !== param.slice(0, 1)) {
+				decorations[param] = params[param];
+				continue;
+			}
+			func = false;
+			val = params[param];
+			args = param.split('/');
+			if (typeof val === "string" && val.indexOf("%%STRING%%") > -1)  {
+				if (val.indexOf("%%PARAM%%") > -1) {
+					func = CSL.substituteTwo(val);
+				} else {
+					func = CSL.substituteOne(val);
+				}
+			} else if (typeof val === "boolean" && !val) {
+				func = CSL.Output.Formatters.passthrough;
+			} else if (typeof val === "function") {
+				func = val;
+			} else {
+				throw "CSL.Compiler: Bad " + mode + " config entry for " + param + ": " + val;
+			}
+			if (args.length === 1) {
+				decorations[args[0]] = func;
+			} else if (args.length === 2) {
+				if (!decorations[args[0]]) {
+					decorations[args[0]] = {};
+				}
+				decorations[args[0]][args[1]] = func;
+			}
+		}
+	}
+	return decorations;
+};
+CSL.setDecorations = function (state, attributes) {
+	var ret, key, pos;
+	ret = [];
+	for (pos in CSL.FORMAT_KEY_SEQUENCE) {
+		if (true) {
+			key = CSL.FORMAT_KEY_SEQUENCE[pos];
+			if (attributes[key]) {
+				ret.push([key, attributes[key]]);
+				delete attributes[key];
+			}
+		}
+	}
+	return ret;
+};
+CSL.compareAmbigConfig = function(a, b) {
+	var ret, pos, len, ppos, llen;
+	if (a.names.length !== b.names.length) {
+		return 1;
+	} else {
+		for (pos = 0, len = a.names.length; pos < len; pos += 1) {
+			if (a.names[pos] !== b.names[pos]) {
+				return 1;
+			} else {
+				for (ppos = 0, llen = a.names[pos]; ppos < llen; ppos += 1) {
+					if (a.givens[pos][ppos] !== b.givens[pos][ppos]) {
+						return 1;
+					}
+				}
+			}
+		}
+	}
+	return 0;
+};
+CSL.cloneAmbigConfig = function (config, oldconfig, tainters) {
+	var ret, param, pos, ppos, len, llen;
+	ret = {};
+	ret.names = [];
+	ret.givens = [];
+	ret.year_suffix = false;
+	ret.disambiguate = false;
+	for (pos = 0, len = config.names.length; pos < len; pos += 1) {
+		param = config.names[pos];
+		if (oldconfig && (!oldconfig.names[pos] || oldconfig.names[pos] !== param)) {
+			for (ppos = 0, llen = tainters.length; ppos < llen; ppos += 1) {
+				this.tmp.taintedItemIDs[tainters[ppos].id] = true;
+			}
+			oldconfig = false;
+		}
+		ret.names[pos] = param;
+	}
+	for (pos = 0, len = config.givens.length; pos < len; pos += 1) {
+		param = [];
+		llen = config.givens[pos].length;
+		for (ppos = 0; ppos < llen; ppos += 1) {
+			if (oldconfig && oldconfig.givens[pos][ppos] !== config.givens[pos][ppos]) {
+				for (ppos = 0, llen = tainters.length; ppos < llen; ppos += 1) {
+					this.tmp.taintedItemIDs[tainters[ppos].id] = true;
+				}
+				oldconfig = false;
+			}
+			param.push(config.givens[pos][ppos]);
+		}
+		ret.givens.push(param);
+	}
+	if (tainters && tainters.length > 1) {
+		if (tainters.length == 2 || (oldconfig && oldconfig.year_suffix !== config.year_suffix)) {
+			for (pos = 0, len = tainters.length; pos < len; pos += 1) {
+				var oldYS = this.registry.registry[tainters[pos].id].disambig.year_suffix;
+				if (tainters && (false === oldYS || oldYS != pos)) {
+					this.tmp.taintedItemIDs[tainters[pos].id] = true;
+				}
+			}
+			oldconfig = false;
+		}
+	}
+	ret.year_suffix = config.year_suffix;
+	ret.disambiguate = config.disambiguate;
+	return ret;
+};
+CSL.getAmbigConfig = function () {
+	var config, ret;
+	config = this.tmp.disambig_request;
+	if (!config) {
+		config = this.tmp.disambig_settings;
+	}
+	ret = CSL.cloneAmbigConfig(config);
+	return ret;
+};
+CSL.getMaxVals = function () {
+	return this.tmp.names_max.mystack.slice();
+};
+CSL.getMinVal = function () {
+	return this.tmp["et-al-min"];
+};
+CSL.tokenExec = function (token, Item, item) {
+	var next, maybenext, exec, pos, len, debug;
+	debug = false;
+    next = token.next;
+	maybenext = false;
+	if (token.evaluator) {
+	    next = token.evaluator(token, this, Item, item);
+    }
+	len = token.execs.length;
+	for (pos = 0; pos < len; pos += 1) {
+		exec = token.execs[pos];
+		maybenext = exec.call(token, this, Item, item);
+		if (maybenext) {
+			next = maybenext;
+		}
+	}
+	if (false) {
+		CSL.debug(token.name + " (" + token.tokentype + ") ---> done");
+	}
+	return next;
+};
+CSL.expandMacro = function (macro_key_token) {
+	var mkey, start_token, key, end_token, navi, macroxml, newoutput, mergeoutput, end_of_macro;
+	mkey = macro_key_token.postponed_macro;
+	if (this.build.macro_stack.indexOf(mkey) > -1) {
+		throw "CSL processor error: call to macro \"" + mkey + "\" would cause an infinite loop";
+	} else {
+		this.build.macro_stack.push(mkey);
+	}
+	macro_key_token.tokentype = CSL.START;
+	CSL.Node.group.build.call(macro_key_token, this, this[this.build.area].tokens, true);
+	macroxml = this.sys.xml.getNodesByName(this.cslXml, 'macro', mkey);
+	if (!this.sys.xml.getNodeValue(macroxml)) {
+		throw "CSL style error: undefined macro \"" + mkey + "\"";
+	}
+	navi = new this.getNavi(this, macroxml);
+	CSL.buildStyle.call(this, navi);
+	end_of_macro = new CSL.Token("group", CSL.END);
+	CSL.Node.group.build.call(end_of_macro, this, this[this.build.area].tokens, true);
+	this.build.macro_stack.pop();
+};
+CSL.XmlToToken = function (state, tokentype) {
+	var name, txt, attrfuncs, attributes, decorations, token, key, target;
+	name = state.sys.xml.nodename(this);
+	if (state.build.skip && state.build.skip !== name) {
+		return;
+	}
+	if (!name) {
+		txt = state.sys.xml.content(this);
+		if (txt) {
+			state.build.text = txt;
+		}
+		return;
+	}
+	if (!CSL.Node[state.sys.xml.nodename(this)]) {
+		throw "Undefined node name \"" + name + "\".";
+	}
+	attrfuncs = [];
+	attributes = state.sys.xml.attributes(this);
+	decorations = CSL.setDecorations.call(this, state, attributes);
+	token = new CSL.Token(name, tokentype);
+	if (tokentype !== CSL.END || name === "if" || name === "else-if" || name === "layout") {
+		for (key in attributes) {
+			if (tokentype === CSL.END && key !== "@language" && key !== "@locale") {
+				continue;
+			}
+			if (attributes.hasOwnProperty(key)) {
+				try {
+					CSL.Attributes[key].call(token, state, "" + attributes[key]);
+				} catch (e) {
+					if (e === "TypeError: Cannot call method \"call\" of undefined") {
+						throw "Unknown attribute \"" + key + "\" in node \"" + name + "\" while processing CSL file";
+					} else {
+						throw "CSL processor error, " + key + " attribute: " + e;
+					}
+				}
+			}
+		}
+		token.decorations = decorations;
+	}
+	target = state[state.build.area].tokens;
+	CSL.Node[name].build.call(token, state, target);
+};
+CSL.DateParser = function (txt) {
+	var jiy_list, jiy, jiysplitter, jy, jmd, jr, pos, key, val, yearlast, yearfirst, number, rangesep, fuzzychar, chars, rex, rexdash, rexdashslash, rexslashdash, seasonstrs, seasonrexes, seasonstr, monthstrs, monthstr, mrexes, seasonrex, len, jiymatchstring, jiymatcher;
+	jiy_list = [
+		["\u660E\u6CBB", 1867],
+		["\u5927\u6B63", 1911],
+		["\u662D\u548C", 1925],
+		["\u5E73\u6210", 1988]
+	];
+	jiy = {};
+	len = jiy_list.length;
+	for (pos = 0; pos < len; pos += 1) {
+		key = jiy_list[pos][0];
+		val = jiy_list[pos][1];
+		jiy[key] = val;
+	}
+	jiymatchstring = [];
+	for (pos = 0; pos < len; pos += 1) {
+		val = jiy_list[pos][0];
+		jiymatchstring.push(val);
+	}
+	jiymatchstring = jiymatchstring.join("|");
+	jiysplitter = "(?:" + jiymatchstring + ")(?:[0-9]+)";
+	jiysplitter = new RegExp(jiysplitter);
+	jiymatcher = "(?:" + jiymatchstring + ")(?:[0-9]+)";
+	jiymatcher = new RegExp(jiymatcher, "g");
+	jmd = /(\u6708|\u5E74)/g;
+	jy = /\u65E5/;
+	jr = /\u301c/g;
+	yearlast = "(?:[?0-9]{1,2}%%NUMD%%){0,2}[?0-9]{4}(?![0-9])";
+	yearfirst = "[?0-9]{4}(?:%%NUMD%%[?0-9]{1,2}){0,2}(?![0-9])";
+	number = "[?0-9]{1,3}";
+	rangesep = "[%%DATED%%]";
+	fuzzychar = "[?~]";
+	chars = "[a-zA-Z]+";
+	rex = "(" + yearfirst + "|" + yearlast + "|" + number + "|" + rangesep + "|" + fuzzychar + "|" + chars + ")";
+	rexdash = new RegExp(rex.replace(/%%NUMD%%/g, "-").replace(/%%DATED%%/g, "-"));
+	rexdashslash = new RegExp(rex.replace(/%%NUMD%%/g, "-").replace(/%%DATED%%/g, "\/"));
+	rexslashdash = new RegExp(rex.replace(/%%NUMD%%/g, "\/").replace(/%%DATED%%/g, "-"));
+	seasonstrs = [];
+	seasonrexes = [];
+	len = seasonstrs.length;
+	for (pos = 0; pos < len; pos += 1) {
+		seasonrex = new RegExp(seasonstrs[pos] + ".*");
+		seasonrexes.push(seasonrex);
+	}
+	this.mstrings = "january february march april may june july august september october november december spring summer fall winter spring summer";
+	this.mstrings = this.mstrings.split(" ");
+	this.setOrderDayMonth = function() {
+		this.monthguess = 1;
+		this.dayguess = 0;
+	}
+	this.setOrderMonthDay = function() {
+		this.monthguess = 0;
+		this.dayguess = 1;
+	}
+	this.setOrderMonthDay();
+	this.resetMonths = function() {
+		this.msets = [];
+		for (var i = 0, ilen = this.mstrings.length; i < ilen; i += 1) {
+			this.msets.push([this.mstrings[i]]);
+		}
+		this.mabbrevs = [];
+		for (var i = 0, ilen = this.msets.length; i < ilen; i += 1) {
+			this.mabbrevs.push([]);
+			for (var j = 0, jlen = this.msets[i].length; j < jlen; j += 1) {
+				this.mabbrevs[i].push(this.msets[i][0].slice(0, 3));
+			}
+		}
+		this.mrexes = [];
+		for (var i = 0, ilen = this.mabbrevs.length; i < ilen; i += 1) {
+			this.mrexes.push(new RegExp("(?:" + this.mabbrevs[i].join("|") + ")"));
+		}
+	}
+	this.resetMonths();
+	this.addMonths = function(lst) {
+		if ("string" === typeof lst) {
+			lst = lst.split(/\s+/);
+		}
+		if (lst.length !== 12 && lst.length !== 16) {
+			CSL.debug("month [+season] list of "+lst.length+", expected 12 or 16. Ignoring.");
+			return;
+		}
+		var othermatch = [];
+		var thismatch = [];
+		for (var i = 0, ilen = lst.length; i < ilen; i += 1) {
+			var abbrevlen = false;
+			var skip = false;
+			var insert = 3;
+			var extend = {};
+			for (var j = 0, jlen = this.mabbrevs.length; j < jlen; j += 1) {
+				extend[j] = {};
+				if (j === i) {
+					for (var k = 0, klen = this.mabbrevs[i].length; k < klen; k += 1) {
+						if (this.mabbrevs[i][k] === lst[i].slice(0, this.mabbrevs[i][k].length)) {
+							skip = true;
+							break;
+						}
+					}
+				} else {
+					for (var k = 0, klen = this.mabbrevs[j].length; k < klen; k += 1) {
+						abbrevlen = this.mabbrevs[j][k].length;
+						if (this.mabbrevs[j][k] === lst[i].slice(0, abbrevlen)) {
+							while (this.msets[j][k].slice(0, abbrevlen) === lst[i].slice(0, abbrevlen)) {
+								if (abbrevlen > lst[i].length || abbrevlen > this.msets[j][k].length) {
+									CSL.debug("unable to disambiguate month string in date parser: "+lst[i]);
+									break;
+								} else {
+									abbrevlen += 1;
+								}
+							}
+							insert = abbrevlen;
+							extend[j][k] = abbrevlen;
+						}
+					}
+				}
+				for (var j in extend) {
+					j = parseInt(j, 10);
+					for (var k in extend[j]) {
+						k = parseInt(k, 10);
+						abbrevlen = extend[j][k];
+						this.mabbrevs[j][k] = this.msets[j][k].slice(0, abbrevlen);
+					}
+				}
+			}
+			if (!skip) {
+				this.msets[i].push(lst[i]);
+				this.mabbrevs[i].push(lst[i].slice(0, insert));
+			}
+		}
+		this.mrexes = [];
+		for (var i = 0, ilen = this.mabbrevs.length; i < ilen; i += 1) {
+			this.mrexes.push(new RegExp("(?:" + this.mabbrevs[i].join("|") + ")"));
+		}
+	}
+	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;
+		m = txt.match(jmd);
+		if (m) {
+			txt = txt.replace(jy, "");
+			txt = txt.replace(jmd, "-");
+			txt = txt.replace(jr, "/");
+			txt = txt.replace("-/", "/");
+			txt = txt.replace(/-$/,"");
+			slst = txt.split(jiysplitter);
+			lst = [];
+			mm = txt.match(jiymatcher);
+			var mmx = [];
+			for (pos = 0, len = mm.length; pos < len; pos += 1) {
+				mmx = mmx.concat(mm[pos].match(/([^0-9]+)([0-9]+)/).slice(1));
+			}
+			for (pos = 0, len = slst.length; pos < len; pos += 1) {
+				lst.push(slst[pos]);
+				if (pos !== (len - 1)) {
+					mmpos = (pos * 2);
+					lst.push(mmx[mmpos]);
+					lst.push(mmx[mmpos + 1]);
+				}
+			}
+			l = lst.length;
+			for	(pos = 1; pos < l; pos += 3) {
+				lst[pos + 1] = jiy[lst[pos]] + parseInt(lst[pos + 1], 10);
+				lst[pos] = "";
+			}
+			txt = lst.join("");
+			txt = txt.replace(/\s*-\s*$/, "").replace(/\s*-\s*\//, "/");
+			txt = txt.replace(/\.\s*$/, "");
+			txt = txt.replace(/\.(?! )/, "");
+			slash = txt.indexOf("/");
+			dash = txt.indexOf("-");
+		}
+		txt = txt.replace(/([A-Za-z])\./g, "$1");
+		number = "";
+		note = "";
+		thedate = {};
+		if (txt.slice(0, 1) === "\"" && txt.slice(-1) === "\"") {
+			thedate.literal = txt.slice(1, -1);
+			return thedate;
+		}
+		if (slash > -1 && dash > -1) {
+			slashcount = txt.split("/");
+			if (slashcount.length > 3) {
+				range_delim = "-";
+				date_delim = "/";
+				lst = txt.split(rexslashdash);
+			} else {
+				range_delim = "/";
+				date_delim = "-";
+				lst = txt.split(rexdashslash);
+			}
+		} else {
+			txt = txt.replace("/", "-");
+			range_delim = "-";
+			date_delim = "-";
+			lst = txt.split(rexdash);
+		}
+		ret = [];
+		len = lst.length;
+		for (pos = 0; pos < len; pos += 1) {
+			item = lst[pos];
+			m = item.match(/^\s*([\-\/]|[a-zA-Z]+|[\-~?0-9]+)\s*$/);
+			if (m) {
+				ret.push(m[1]);
+			}
+		}
+		delim_pos = ret.indexOf(range_delim);
+		delims = [];
+		isrange = false;
+		if (delim_pos > -1) {
+			delims.push([0, delim_pos]);
+			delims.push([(delim_pos + 1), ret.length]);
+			isrange = true;
+		} else {
+			delims.push([0, ret.length]);
+		}
+		suff = "";
+		for (i = 0, ilen = delims.length; i < ilen; i += 1) {
+			delim = delims[i];
+			date = ret.slice(delim[0], delim[1]);
+			for (j = 0, jlen = date.length; j < jlen; j += 1) {
+				element = date[j];
+				if (element.indexOf(date_delim) > -1) {
+					this.parseNumericDate(thedate, date_delim, suff, element);
+					continue;
+				}
+				if (element.match(/[0-9]{4}/)) {
+					thedate[("year" + suff)] = element.replace(/^0*/, "");
+					continue;
+				}
+				breakme = false;
+				for (k = 0, klen = this.mrexes.length; k < klen; k += 1) {
+					if (element.toLocaleLowerCase().match(this.mrexes[k])) {
+						thedate[("month" + suff)] = "" + (parseInt(k, 10) + 1);
+						breakme = true;
+						break;
+					}
+					if (breakme) {
+						continue;
+					}
+					if (element.match(/^[0-9]+$/)) {
+						number = parseInt(element, 10);
+					}
+					if (element.toLocaleLowerCase().match(/^bc/) && number) {
+						thedate[("year" + suff)] = "" + (number * -1);
+						number = "";
+						continue;
+					}
+					if (element.toLocaleLowerCase().match(/^ad/) && number) {
+						thedate[("year" + suff)] = "" + number;
+						number = "";
+						continue;
+					}
+				}
+				breakme = false;
+				lllen = seasonrexes.length;
+				for (k = 0, klen = seasonrexes.length; k < klen; k += 1) {
+					if (element.toLocaleLowerCase().match(seasonrexes[k])) {
+						thedate[("season" + suff)] = "" + (parseInt(k, 10) + 1);
+						breakme = true;
+						break;
+					}
+				}
+				if (breakme) {
+					continue;
+				}
+				if (element === "~" || element === "?" || element === "c" || element.match(/^cir/)) {
+					thedate.circa = "" + 1;
+					continue;
+				}
+				if (element.toLocaleLowerCase().match(/(?:mic|tri|hil|eas)/) && !thedate[("season" + suff)]) {
+					note = element;
+					continue;
+				}
+			}
+			if (number) {
+				thedate[("day" + suff)] = number;
+				number = "";
+			}
+			if (note && !thedate[("season" + suff)]) {
+				thedate[("season" + suff)] = note;
+				note = "";
+			}
+			suff = "_end";
+		}
+		if (isrange) {
+			for (j = 0, jlen = CSL.DATE_PARTS_ALL.length; j < jlen; j += 1) {
+				item = CSL.DATE_PARTS_ALL[j];
+				if (thedate[item] && !thedate[(item + "_end")]) {
+					thedate[(item + "_end")] = thedate[item];
+				} else if (!thedate[item] && thedate[(item + "_end")]) {
+					thedate[item] = thedate[(item + "_end")];
+				}
+			}
+		}
+		if (!thedate.year) {
+			thedate = { "literal": txt };
+		}
+		if (this.use_array) {
+			this.toArray(thedate);			
+		}
+		return thedate;
+	};
+	this.returnAsArray = function () {
+		this.use_array = true;
+	}
+	this.returnAsKeys = function () {
+		this.use_array = false;
+	}
+	this.toArray = function (thedate) {
+		thedate["date-parts"] = [];
+		thedate["date-parts"].push([]);
+		var slicelen = 0;
+		for (var i = 0, ilen = 3; i < ilen; i += 1) {
+			var part = ["year", "month", "day"][i];
+			if (!thedate[part]) {
+				break;
+			}
+			slicelen += 1;
+			thedate["date-parts"][0].push(thedate[part]);
+			delete thedate[part];
+		}
+		for (var i = 0, ilen = slicelen; i < ilen; i += 1) {
+			var part = ["year_end", "month_end", "day_end"][i];
+			if (thedate[part] && thedate["date-parts"].length === 1) {
+				thedate["date-parts"].push([]);
+			}
+			thedate["date-parts"][1].push(thedate[part]);
+			delete thedate[part];
+		}
+	}
+	this.parseNumericDate = function (ret, delim, suff, txt) {
+		var lst, pos, len;
+		lst = txt.split(delim);
+		for (i = 0, ilen = lst.length; i < ilen; i += 1) {
+			if (lst[i].length === 4) {
+				ret[("year" + suff)] = lst[i].replace(/^0*/, "");
+				if (!i) {
+					lst = lst.slice(1);
+				} else {
+					lst = lst.slice(0, i);
+				}
+				break;
+			}
+		}
+		for (i = 0, ilen = lst.length; i < ilen; i += 1) {
+			lst[i] = parseInt(lst[i], 10);
+		}
+		if (lst.length === 1) {
+			ret[("month" + suff)] = "" + lst[0];
+		} else if (lst.length === 2) {
+			if (lst[this.monthguess] > 12) {
+				ret[("month" + suff)] = "" + lst[this.dayguess];
+				ret[("day" + suff)] = "" + lst[this.monthguess];
+			} else {
+				ret[("month" + suff)] = "" + lst[this.monthguess];
+				ret[("day" + suff)] = "" + lst[this.dayguess];
+			}
+		}
+	};
+};
+CSL.Engine = function (sys, style, lang, forceLang) {
+	var attrs, langspec, localexml, locale;
+	this.processor_version = "1.0.124";
+	this.csl_version = "1.0";
+	this.sys = sys;
+	this.sys.xml = new CSL.System.Xml.Parsing();
+	if ("string" !== typeof style) {
+		style = "";
+	}
+	this.parallel = new CSL.Parallel(this);
+	this.transform = new CSL.Transform(this);
+	this.setAbbreviations = function (nick) {
+		this.transform.setAbbreviations(nick);
+	};
+	this.setParseNames = function (val) {
+		this.opt['parse-names'] = val;
+	};
+	this.opt = new CSL.Engine.Opt();
+	this.tmp = new CSL.Engine.Tmp();
+	this.build = new CSL.Engine.Build();
+	this.fun = new CSL.Engine.Fun();
+	this.configure = new CSL.Engine.Configure();
+	this.citation_sort = new CSL.Engine.CitationSort();
+	this.bibliography_sort = new CSL.Engine.BibliographySort();
+	this.citation = new CSL.Engine.Citation(this);
+	this.bibliography = new CSL.Engine.Bibliography();
+	this.output = new CSL.Output.Queue(this);
+	this.dateput = new CSL.Output.Queue(this);
+	this.cslXml = this.sys.xml.makeXml(style);
+	this.sys.xml.addInstitutionNodes(this.cslXml);
+	attrs = this.sys.xml.attributes(this.cslXml);
+	if ("undefined" === typeof attrs["@sort-separator"]) {
+		this.sys.xml.setAttribute(this.cslXml, "sort-separator", ", ");
+	}
+	if ("undefined" === typeof attrs["@name-delimiter"]) {
+		this.sys.xml.setAttribute(this.cslXml, "name-delimiter", ", ");
+	}
+	this.opt["initialize-with-hyphen"] = true;
+	this.setStyleAttributes();
+	CSL.Util.Names.initNameSlices(this);
+	this.opt.xclass = sys.xml.getAttributeValue(this.cslXml, "class");
+	if (lang) {
+		lang = lang.replace("_", "-");
+	}
+	if (this.opt["default-locale"][0]) {
+		this.opt["default-locale"][0] = this.opt["default-locale"][0].replace("_", "-");
+	}
+	if (lang && forceLang) {
+		this.opt["default-locale"] = [lang];
+	}
+	if (lang && !forceLang && this.opt["default-locale"][0]) {
+		lang = this.opt["default-locale"][0];
+	}
+	if (this.opt["default-locale"].length === 0) {
+		if (!lang) {
+			lang = "en-US";
+		}
+		this.opt["default-locale"].push("en-US");
+	}
+	if (!lang) {
+		lang = this.opt["default-locale"][0];
+	}
+	langspec = CSL.localeResolve(lang);
+	this.opt.lang = langspec.best;
+	this.opt["default-locale"][0] = langspec.best;
+	this.locale = {};
+	this.localeConfigure(langspec);
+	this.buildTokenLists("citation");
+	this.buildTokenLists("bibliography");
+	this.configureTokenLists();
+	this.registry = new CSL.Registry(this);
+	this.disambiguate = new CSL.Disambiguation(this);
+	this.splice_delimiter = false;
+	this.fun.dateparser = new CSL.DateParser();
+	this.fun.flipflopper = new CSL.Util.FlipFlopper(this);
+	this.setCloseQuotesArray();
+	this.fun.ordinalizer.init(this);
+	this.fun.long_ordinalizer.init(this);
+	this.fun.page_mangler = CSL.Util.PageRangeMangler.getFunction(this);
+	this.setOutputFormat("html");
+};
+CSL.Engine.prototype.setCloseQuotesArray = function () {
+	var ret;
+	ret = [];
+	ret.push(this.getTerm("close-quote"));
+	ret.push(this.getTerm("close-inner-quote"));
+	ret.push('"');
+	ret.push("'");
+	this.opt.close_quotes_array = ret;
+};
+CSL.Engine.prototype.buildTokenLists = function (area) {
+	var area_nodes, navi;
+	area_nodes = this.sys.xml.getNodesByName(this.cslXml, area);
+	if (!this.sys.xml.getNodeValue(area_nodes)) {
+		return;
+	}
+	navi = new this.getNavi(this, area_nodes);
+	this.build.area = area;
+	CSL.buildStyle.call(this, navi);
+};
+CSL.Engine.prototype.setStyleAttributes = function () {
+	var dummy, attr, key, attributes, attrname;
+	dummy = {};
+	dummy.name = this.sys.xml.nodename(this.cslXml);
+	attributes = this.sys.xml.attributes(this.cslXml);
+	for (attrname in attributes) {
+		if (attributes.hasOwnProperty(attrname)) {
+			CSL.Attributes[attrname].call(dummy, this, attributes[attrname]);
+		}
+	}
+};
+CSL.buildStyle  = function (navi) {
+	if (navi.getkids()) {
+		CSL.buildStyle.call(this, navi);
+	} else {
+		if (navi.getbro()) {
+			CSL.buildStyle.call(this, navi);
+		} else {
+			while (navi.nodeList.length > 1) {
+				if (navi.remember()) {
+					CSL.buildStyle.call(this, navi);
+				}
+			}
+		}
+	}
+};
+CSL.Engine.prototype.getNavi = function (state, myxml) {
+	this.sys = state.sys;
+	this.state = state;
+	this.nodeList = [];
+	this.nodeList.push([0, myxml]);
+	this.depth = 0;
+};
+CSL.Engine.prototype.getNavi.prototype.remember = function () {
+	var node;
+	this.depth += -1;
+	this.nodeList.pop();
+	node = this.nodeList[this.depth][1][(this.nodeList[this.depth][0])];
+	CSL.XmlToToken.call(node, this.state, CSL.END);
+	return this.getbro();
+};
+CSL.Engine.prototype.getNavi.prototype.getbro = function () {
+	var sneakpeek;
+	sneakpeek = this.nodeList[this.depth][1][(this.nodeList[this.depth][0] + 1)];
+	if (sneakpeek) {
+		this.nodeList[this.depth][0] += 1;
+		return true;
+	} else {
+		return false;
+	}
+};
+CSL.Engine.prototype.getNavi.prototype.getkids = function () {
+	var currnode, sneakpeek, pos, node, len;
+	currnode = this.nodeList[this.depth][1][this.nodeList[this.depth][0]];
+	sneakpeek = this.sys.xml.children(currnode);
+	if (this.sys.xml.numberofnodes(sneakpeek) === 0) {
+		CSL.XmlToToken.call(currnode, this.state, CSL.SINGLETON);
+		return false;
+	} else {
+		for (pos in sneakpeek) {
+			if (true) {
+				node = sneakpeek[pos];
+				if ("date" === this.sys.xml.nodename(node)) {
+					currnode = CSL.Util.fixDateNode.call(this, currnode, pos, node);
+					sneakpeek = this.sys.xml.children(currnode);
+				}
+			}
+		}
+		CSL.XmlToToken.call(currnode, this.state, CSL.START);
+		this.depth += 1;
+		this.nodeList.push([0, sneakpeek]);
+		return true;
+	}
+};
+CSL.Engine.prototype.getNavi.prototype.getNodeListValue = function () {
+	return this.nodeList[this.depth][1];
+};
+CSL.Engine.prototype.getTerm = function (term, form, plural, gender, loose) {
+	var ret = CSL.Engine.getField(CSL.LOOSE, this.locale[this.opt.lang].terms, term, form, plural, gender);
+	if (typeof ret === "undefined") {
+		ret = CSL.Engine.getField(CSL.STRICT, this.locale[this.opt.lang].terms, term, form, plural, gender);
+	}
+	if (ret) {
+		this.tmp.cite_renders_content = true;
+	}
+	return ret;
+};
+CSL.Engine.prototype.getDate = function (form) {
+	if (this.locale[this.opt.lang].dates[form]) {
+		return this.locale[this.opt.lang].dates[form];
+	} else {
+		return false;
+	}
+};
+CSL.Engine.prototype.getOpt = function (arg) {
+	if ("undefined" !== typeof this.locale[this.opt.lang].opts[arg]) {
+		return this.locale[this.opt.lang].opts[arg];
+	} else {
+		return this.locale[this.opt.lang].opts[arg];
+	}
+};
+CSL.Engine.prototype.getVariable = function (Item, varname, form, plural) {
+	return CSL.Engine.getField(CSL.LOOSE, Item, varname, form, plural);
+};
+CSL.Engine.prototype.getDateNum = function (ItemField, partname) {
+	if ("undefined" === typeof ItemField) {
+		return 0;
+	} else {
+		return ItemField[partname];
+	}
+};
+CSL.Engine.getField = function (mode, hash, term, form, plural, gender) {
+	var ret, forms, f, pos, len, hashterm;
+	ret = "";
+	if ("undefined" === typeof hash[term]) {
+		if (mode === CSL.STRICT) {
+			throw "Error in getField: term \"" + term + "\" does not exist.";
+		} else {
+			return undefined;
+		}
+	}
+	if (gender && hash[term][gender]) {
+		hashterm = hash[term][gender];
+	} else {
+		hashterm = hash[term];
+	}
+	forms = [];
+	if (form === "symbol") {
+		forms = ["symbol", "short"];
+	} else if (form === "verb-short") {
+		forms = ["verb-short", "verb"];
+	} else if (form !== "long") {
+		forms = [form];
+	}
+	forms = forms.concat(["long"]);
+	len = forms.length;
+	for (pos = 0; pos < len; pos += 1) {
+		f = forms[pos];
+		if ("string" === typeof hashterm || "number" === typeof hashterm) {
+			ret = hashterm;
+		} else if ("undefined" !== typeof hashterm[f]) {
+			if ("string" === typeof hashterm[f] || "number" === typeof hashterm[f]) {
+				ret = hashterm[f];
+			} else {
+				if ("number" === typeof plural) {
+					ret = hashterm[f][plural];
+				} else {
+					ret = hashterm[f][0];
+				}
+			}
+			break;
+		}
+	}
+	return ret;
+};
+CSL.Engine.prototype.configureTokenLists = function () {
+	var dateparts_master, area, pos, token, dateparts, part, ppos, pppos, len, llen, lllen;
+	dateparts_master = ["year", "month", "day"];
+	len = CSL.AREAS.length;
+	for (pos = 0; pos < len; pos += 1) {
+		area = CSL.AREAS[pos];
+		llen = this[area].tokens.length - 1;
+		for (ppos = llen; ppos > -1; ppos += -1) {
+			token = this[area].tokens[ppos];
+			if ("date" === token.name && CSL.END === token.tokentype) {
+				dateparts = [];
+			}
+			if ("date-part" === token.name && token.strings.name) {
+				lllen = dateparts_master.length;
+				for (pppos = 0; pppos < lllen; pppos += 1) {
+					part = dateparts_master[pppos];
+					if (part === token.strings.name) {
+						dateparts.push(token.strings.name);
+					}
+				}
+			}
+			if ("date" === token.name && CSL.START === token.tokentype) {
+				dateparts.reverse();
+				token.dateparts = dateparts;
+			}
+			token.next = (ppos + 1);
+			if (token.name && CSL.Node[token.name].configure) {
+				CSL.Node[token.name].configure.call(token, this, ppos);
+			}
+		}
+	}
+	this.version = CSL.version;
+	return this.state;
+};
+CSL.Engine.prototype.retrieveItems = function (ids) {
+	var ret, pos, len;
+	ret = [];
+	len = ids.length;
+	for (pos = 0; pos < len; pos += 1) {
+		ret.push(this.retrieveItem("" + ids[pos]));
+	}
+	return ret;
+};
+CSL.Engine.prototype.retrieveItem = function (id) {
+	var Item, m, pos, len, mm;
+	Item = this.sys.retrieveItem("" + id);
+	if (Item.note) {
+		m = CSL.NOTE_FIELDS_REGEXP.exec(Item.note);
+		if (m) {
+			for (pos = 0, len = m.length; pos < len; pos += 1) {
+				mm = CSL.NOTE_FIELD_REGEXP.exec(m[pos]);
+				if (!Item[mm[1]]) {
+					Item[mm[1]] = mm[2].replace(/^\s+/, "").replace(/\s+$/, "");
+				}
+			}
+		}
+	}
+	return Item;
+};
+CSL.Engine.prototype.dateParseArray = function (date_obj) {
+	var ret, field, dpos, ppos, dp, exts, llen, pos, len, pppos, lllen;
+	ret = {};
+	for (field in date_obj) {
+		if (field === "date-parts") {
+			dp = date_obj["date-parts"];
+			if (dp.length > 1) {
+				if (dp[0].length !== dp[1].length) {
+					CSL.error("CSL data error: element mismatch in date range input.");
+				}
+			}
+			exts = ["", "_end"];
+			llen = dp.length;
+			for (ppos = 0; ppos < llen; ppos += 1) {
+				lllen = CSL.DATE_PARTS.length;
+				for (pppos = 0; pppos < lllen; pppos += 1) {
+					ret[(CSL.DATE_PARTS[pppos] + exts[ppos])] = dp[ppos][pppos];
+				}
+			}
+		} else if (date_obj.hasOwnProperty(field)) {
+			if (field === "literal" && "object" === typeof date_obj.literal && "string" === typeof date_obj.literal.part) {
+				CSL.error("CSL: fixing up weird literal date value");
+				ret.literal = date_obj.literal.part;
+			} else {
+				ret[field] = date_obj[field];
+			}
+		}
+	}
+	return ret;
+};
+CSL.Engine.prototype.setOpt = function (token, name, value) {
+	if (token.name === "style") {
+		this.opt[name] = value;
+	} else if (["citation", "bibliography"].indexOf(token.name) > -1) {
+		this[token.name].opt[name] = value;
+	} else if (["name-form", "name-delimiter", "names-delimiter"].indexOf(name) === -1) {
+		token.strings[name] = value;
+	}
+};
+CSL.Engine.prototype.fixOpt = function (token, name, localname) {
+	if ("citation" === token.name || "bibliography" === token.name) {
+		if (! this[token.name].opt[name] && "undefined" !== this.opt[name]) {
+			this[token.name].opt[name] = this.opt[name];
+		}
+	}
+	if ("name" === token.name || "names" === token.name) {
+		if (! token.strings[localname] && "undefined" !== typeof this[this.build.area].opt[name]) {
+			token.strings[localname] = this[this.build.area].opt[name];
+		}
+	}
+};
+CSL.Engine.prototype.setOutputFormat = function (mode) {
+	this.opt.mode = mode;
+	this.fun.decorate = CSL.Mode(mode);
+	if (!this.output[mode]) {
+		this.output[mode] = {};