diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js
index 5c6b7b135..3e0a4964a 100644
--- a/chrome/content/zotero/xpcom/citeproc.js
+++ b/chrome/content/zotero/xpcom/citeproc.js
@@ -23,7 +23,7 @@
* respectively.
*/
var CSL = {
- PROCESSOR_VERSION: "1.1.139",
+ PROCESSOR_VERSION: "1.1.165",
CONDITION_LEVEL_TOP: 1,
CONDITION_LEVEL_BOTTOM: 2,
PLAIN_HYPHEN_REGEX: /(?:[^\\]-|\u2013)/,
@@ -196,6 +196,36 @@ var CSL = {
this["container-phrase"] = {};
this["title-phrase"] = {};
},
+ FIELD_CATEGORY_REMAP: {
+ "title": "title",
+ "container-title": "container-title",
+ "collection-title": "collection-title",
+ "number": "number",
+ "place": "place",
+ "archive": "collection-title",
+ "title-short": "title",
+ "genre": "title",
+ "event": "title",
+ "medium": "title",
+ "archive-place": "place",
+ "publisher-place": "place",
+ "event-place": "place",
+ "jurisdiction": "place",
+ "language-name": "place",
+ "language-name-original": "place",
+ "call-number": "number",
+ "chapter-number": "number",
+ "collection-number": "number",
+ "edition": "number",
+ "page": "number",
+ "issue": "number",
+ "locator": "number",
+ "number-of-pages": "number",
+ "number-of-volumes": "number",
+ "volume": "number",
+ "citation-number": "number",
+ "publisher": "institution-part"
+ },
parseLocator: function(item) {
if (this.opt.development_extensions.locator_date_and_revision) {
if (item.locator) {
@@ -408,6 +438,8 @@ var CSL = {
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]+|[A-Z]+):[^\}]+\}/g,
NOTE_FIELD_REGEXP: /^([\-_a-z]+|[A-Z]+):\s*([^\}]+)$/,
+ PARTICLE_GIVEN_REGEXP: /^([^ ]+(?:\u02bb |\u2019 | |\' ) *)(.+)$/,
+ PARTICLE_FAMILY_REGEXP: /^([^ ]+(?:\-|\u02bb|\u2019| |\') *)(.+)$/,
DISPLAY_CLASSES: ["block", "left-margin", "right-inline", "indent"],
NAME_VARIABLES: [
"author",
@@ -449,62 +481,13 @@ var CSL = {
"available-date",
"submitted"
],
- TAG_ESCAPE: function (str, stopWords) {
- var mx, lst, len, pos, m, buf1, buf2, idx, ret, myret;
- if (!stopWords) {
- stopWords = [];
+ TITLE_FIELD_SPLITS: function(seg) {
+ var keys = ["title", "short", "main", "sub"];
+ var ret = {};
+ for (var i=0,ilen=keys.length;i": "",
- "": ""
- };
- var stack = [];
- str = str.replace(/()/g, "$1 $2$3");
- var m1match = str.match(/((?: \"| \'|\" |\'[-.,;\?:]|\[|\]|\(|\)||<\/span>|<\/?(?:i|sc|b|sub|sup)>))/g);
- if (!m1match) {
- return [str];
- }
- var m1split = str.split(/(?: \"| \'|\" |\'[-.,;\?:]|\[|\]|\(|\)||<\/span>|<\/?(?:i|sc|b|sub|sup)>)/g);
- outer: for (var i=0,ilen=m1match.length; i -1) {
- if (!m1split[i-1].match(/[:\?\!]\s*$/)) {
- m1match[i-1] = m1match[i-1] + mFirstWord[1];
- m1split[i] = mFirstWord[3];
- }
- }
- }
- continue;
- }
- if (stack.length) {
- for (var j=stack.length-1; j>-1; j--) {
- var stackObj = stack.slice(j)[0];
- if (m1match[i] === pairs[stackObj.tag]) {
- stack = stack.slice(0, j+1);
- var startPos = stack[j].pos;
- for (var k=stack[j].pos+1; k -1; j += -1) {
+ if (SKIP_WORDS.indexOf(fld[j].toLowerCase()) > -1) {
+ toEnd.push(fld.pop());
+ } else {
+ break;
+ }
+ }
+ fld.reverse();
+ var start = fld.join(" ");
+ var end = toEnd.join(" ");
+ if ("drop" === drop_or_demote || !end) {
+ fld = start;
+ } else if ("demote" === drop_or_demote) {
+ fld = [start, end].join(", ");
+ }
+ }
+ return fld;
+ },
+ extractTitleAndSubtitle: function (Item) {
+ var segments = ["", "container-"];
+ for (var i=0,ilen=segments.length;i -1) {
+ var callbacks = [];
+ if (state.opt.development_extensions.thin_non_breaking_space_html_hack && state.opt.mode === "html") {
+ callbacks.push(function (txt) {
+ return txt.replace(/\u202f/g, ' ');
+ });
+ }
+ if (callbacks.length) {
+ return function (txt) {
+ for (var i = 0, ilen = callbacks.length; i < ilen; i += 1) {
+ txt = callbacks[i](txt);
+ }
+ return CSL.Output.Formats[state.opt.mode].text_escape(txt);
+ }
+ } else {
+ return CSL.Output.Formats[state.opt.mode].text_escape;
+ }
+ } else {
+ return function (txt) { return txt; };
+ }
+ },
SKIP_WORDS: ["about","above","across","afore","after","against","along","alongside","amid","amidst","among","amongst","anenst","apropos","apud","around","as","aside","astride","at","athwart","atop","barring","before","behind","below","beneath","beside","besides","between","beyond","but","by","circa","despite","down","during","except","for","forenenst","from","given","in","inside","into","lest","like","modulo","near","next","notwithstanding","of","off","on","onto","out","over","per","plus","pro","qua","sans","since","than","through"," thru","throughout","thruout","till","to","toward","towards","under","underneath","until","unto","up","upon","versus","vs.","v.","vs","v","via","vis-à-vis","with","within","without","according to","ahead of","apart from","as for","as of","as per","as regards","aside from","back to","because of","close to","due to","except for","far from","inside of","instead of","near to","next to","on to","out from","out of","outside of","prior to","pursuant to","rather than","regardless of","such as","that of","up to","where as","or", "yet", "so", "for", "and", "nor", "a", "an", "the", "de", "d'", "von", "van", "c", "et", "ca"],
FORMAT_KEY_SEQUENCE: [
"@strip-periods",
@@ -1038,6 +1153,9 @@ CSL.XmlJSON.prototype.getNodesByName = function (myjson,name,nameattrval,ret) {
return ret;
}
CSL.XmlJSON.prototype.nodeNameIs = function (myjson,name) {
+ if (typeof myjson === "undefined") {
+ return false;
+ }
if (name == myjson.name) {
return true;
}
@@ -1753,10 +1871,10 @@ CSL.setupXml = function(xmlObject) {
parser = new CSL.XmlJSON(xmlObject);
}
} else {
- print("OUCH!");
+ CSL.error("unable to parse XML input");
}
if (!parser) {
- throw "citeproc-js error: unable to parse style or locale object";
+ throw "citeproc-js error: unable to parse CSL style or locale object";
}
return parser;
}
@@ -2237,8 +2355,18 @@ CSL.DateParser = new function () {
var orig = txt;
var slashPos = -1;
var dashPos = -1;
+ var yearIsNegative = false;
var lst;
if (txt) {
+ if (txt.slice(0, 1) === "-") {
+ yearIsNegative = true;
+ txt = txt.slice(1);
+ }
+ if (txt.match(/^[0-9]{1,3}$/)) {
+ while (txt.length < 4) {
+ txt = "0" + txt;
+ }
+ }
txt = "" + txt;
txt = txt.replace(/\s*[0-9]{2}:[0-9]{2}(?::[0-9]+)/,"");
var m = txt.match(kanjiMonthDay);
@@ -2400,6 +2528,9 @@ CSL.DateParser = new function () {
thedate[part] = parseInt(thedate[part], 10);
}
}
+ if (yearIsNegative && Object.keys(thedate).indexOf("year") > -1) {
+ thedate.year = (thedate.year * -1);
+ }
return thedate;
};
this.parseDateToArray = function(txt) {
@@ -2476,7 +2607,7 @@ CSL.Engine = function (sys, style, lang, forceLang) {
this.opt["initialize-with-hyphen"] = true;
this.setStyleAttributes();
this.opt.xclass = this.cslXml.getAttributeValue(this.cslXml.dataObj, "class");
- this.opt.class = this.opt.xclass;
+ this.opt["class"] = this.opt.xclass;
this.opt.styleID = this.cslXml.getStyleId(this.cslXml.dataObj);
if (CSL.setSuppressedJurisdictions) {
CSL.setSuppressedJurisdictions(this.opt.styleID, this.opt.suppressedJurisdictions);
@@ -2893,35 +3024,20 @@ CSL.Engine.prototype.retrieveItem = function (id) {
Item.legislation_id = legislation_id.join("::");
}
}
+ if (this.opt.development_extensions.force_jurisdiction) {
+ if ("string" === typeof Item.authority) {
+ Item.authority = [
+ {
+ literal: Item.authority
+ }
+ ]
+ }
+ }
if (!Item["title-short"]) {
Item["title-short"] = Item.shortTitle;
}
if (this.opt.development_extensions.main_title_from_short_title) {
- var segments = ["", "container-"];
- for (var i=0,ilen=segments.length;i -1;
if (this.opt.development_extensions.force_jurisdiction && isLegalType) {
@@ -3137,6 +3253,40 @@ CSL.setDecorations = function (state, attributes) {
}
return ret;
};
+CSL.Doppeler = function(rexStr, stringMangler) {
+ var mx, lst, len, pos, m, buf1, buf2, idx, ret, myret;
+ this.split = split;
+ this.join = join;
+ var matchRex = new RegExp("(" + rexStr + ")", "g");
+ var splitRex = new RegExp(rexStr, "g");
+ function split(str) {
+ if (stringMangler) {
+ str = stringMangler(str);
+ }
+ var match = str.match(matchRex);
+ if (!match) {
+ return {
+ tags: [],
+ strings: [str]
+ };
+ }
+ var split = str.split(splitRex);
+ return {
+ tags: match,
+ strings: split,
+ origStrings: split.slice()
+ }
+ }
+ function join(obj) {
+ var lst = obj.strings.slice(-1);
+ for (var i=obj.tags.length-1; i>-1; i--) {
+ lst.push(obj.tags[i]);
+ lst.push(obj.strings[i]);
+ }
+ lst.reverse();
+ return lst.join("");
+ }
+}
CSL.Engine.prototype.normalDecorIsOrphan = function (blob, params) {
if (params[1] === "normal") {
var use_param = false;
@@ -3161,6 +3311,52 @@ CSL.Engine.prototype.normalDecorIsOrphan = function (blob, params) {
}
return false;
};
+CSL.getJurisdictionNameAndSuppress = function(state, jurisdictionID, jurisdictionName) {
+ var ret = null;
+ if (!jurisdictionName) {
+ jurisdictionName = state.sys.getHumanForm(jurisdictionID);
+ }
+ if (!jurisdictionName) {
+ ret = jurisdictionID;
+ } else {
+ var code = jurisdictionID.split(":");
+ var name = jurisdictionName.split("|");
+ var valid = false;
+ if (code.length === 1 && name.length === 2) {
+ valid = true;
+ } else if (code.length > 1 && name.length === code.length) {
+ valid = true;
+ }
+ if (!valid) {
+ ret = name.join("|");
+ } else {
+ var mask = 0;
+ var stub;
+ for (var i=0,ilen=code.length;i -1) {
@@ -7753,11 +7953,13 @@ CSL.NameOutput.prototype.init = function (names) {
this.name = undefined;
this.institutionpart = {};
this.state.tmp.group_context.tip.variable_attempt = true;
+ this.labelVariable = this.variables[0];
if (!this.state.tmp.value.length) {
return;
}
};
-CSL.NameOutput.prototype.reinit = function (names) {
+CSL.NameOutput.prototype.reinit = function (names, labelVariable) {
+ this.labelVariable = labelVariable;
if (this.state.tmp.can_substitute.value()) {
this.nameset_offset = 0;
this.variables = names.variables;
@@ -7911,7 +8113,7 @@ CSL.NameOutput.prototype.outputNames = function () {
};
CSL.NameOutput.prototype._applyLabels = function (blob, v) {
var txt;
- if (!this.label || !this.label[v]) {
+ if (!this.label || !this.label[this.labelVariable]) {
return blob;
}
var plural = 0;
@@ -7926,24 +8128,24 @@ CSL.NameOutput.prototype._applyLabels = function (blob, v) {
plural = 1;
}
}
- if (this.label[v].before) {
- if ("number" === typeof this.label[v].before.strings.plural) {
- plural = this.label[v].before.strings.plural;
+ if (this.label[this.labelVariable].before) {
+ if ("number" === typeof this.label[this.labelVariable].before.strings.plural) {
+ plural = this.label[this.labelVariable].before.strings.plural;
}
- txt = this._buildLabel(v, plural, "before", v);
+ txt = this._buildLabel(v, plural, "before", this.labelVariable);
this.state.output.openLevel("empty");
- this.state.output.append(txt, this.label[v].before, true);
+ this.state.output.append(txt, this.label[this.labelVariable].before, true);
this.state.output.append(blob, "literal", true);
this.state.output.closeLevel("empty");
blob = this.state.output.pop();
- } else if (this.label[v].after) {
- if ("number" === typeof this.label[v].after.strings.plural) {
- plural = this.label[v].after.strings.plural;
+ } else if (this.label[this.labelVariable].after) {
+ if ("number" === typeof this.label[this.labelVariable].after.strings.plural) {
+ plural = this.label[this.labelVariable].after.strings.plural;
}
- txt = this._buildLabel(v, plural, "after", v);
+ txt = this._buildLabel(v, plural, "after", this.labelVariable);
this.state.output.openLevel("empty");
this.state.output.append(blob, "literal", true);
- this.state.output.append(txt, this.label[v].after, true);
+ this.state.output.append(txt, this.label[this.labelVariable].after, true);
this.state.tmp.label_blob = this.state.output.pop();
this.state.output.append(this.state.tmp.label_blob,"literal",true);
this.state.output.closeLevel("empty");
@@ -8556,11 +8758,11 @@ CSL.NameOutput.prototype._runDisambigNames = function (lst, pos) {
}
chk = this.state.tmp.disambig_settings.givens[pos][i];
if ("undefined" === typeof chk) {
- myform = this.state.inheritOpt(this.name, "form", "name-form", "long");
+ myform = this.state.inheritOpt(this.name, "form", "name-form");
param = this.state.registry.namereg.evalname("" + this.Item.id, lst[i], i, 0, myform, myinitials);
this.state.tmp.disambig_settings.givens[pos].push(param);
}
- myform = this.state.inheritOpt(this.name, "form", "name-form", "long");
+ myform = this.state.inheritOpt(this.name, "form", "name-form");
paramx = this.state.registry.namereg.evalname("" + this.Item.id, lst[i], i, 0, myform, myinitials);
if (this.state.tmp.disambig_request) {
var val = this.state.tmp.disambig_settings.givens[pos][i];
@@ -8572,7 +8774,7 @@ CSL.NameOutput.prototype._runDisambigNames = function (lst, pos) {
}
param = val;
if (this.state.opt["disambiguate-add-givenname"] && lst[i].given) {
- param = this.state.registry.namereg.evalname("" + this.Item.id, lst[i], i, param, this.state.inheritOpt(this.name, "form", "name-form", "long"), this.state.inheritOpt(this.name, "initialize-with"));
+ param = this.state.registry.namereg.evalname("" + this.Item.id, lst[i], i, param, this.state.inheritOpt(this.name, "form", "name-form"), this.state.inheritOpt(this.name, "initialize-with"));
}
} else {
param = paramx;
@@ -8829,7 +9031,9 @@ CSL.NameOutput.prototype._renderInstitutionName = function (v, name, slot, j) {
institution = [this._composeOneInstitutionPart([n.l.pri, n.l.sec, n.l.ter], slot, long_style, v)];
break;
}
- return this._join(institution, " ");
+ var blob = this._join(institution, " ");
+ this.state.tmp.name_node.children.push(blob);
+ return blob;
};
CSL.NameOutput.prototype._composeOneInstitutionPart = function (names, slot, style, v) {
var primary = false, secondary = false, tertiary = false, primary_tok, secondary_tok, tertiary_tok;
@@ -9061,7 +9265,20 @@ CSL.NameOutput.prototype._renderOnePersonalName = function (value, pos, i, j) {
suffix_sep = " ";
}
var romanesque = this._isRomanesque(name);
- var has_hyphenated_non_dropping_particle = (non_dropping_particle && ["\u2019", "\'", "-", " "].indexOf(non_dropping_particle.blobs.slice(-1)) > -1);
+ function hasJoiningPunctuation(blob) {
+ if (!blob) {
+ return false;
+ } else if ("string" === typeof blob.blobs) {
+ if (["\u2019", "\'", "-", " "].indexOf(blob.blobs.slice(-1)) > -1) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return hasJoiningPunctuation(blob.blobs[blob.blobs.length-1]);
+ }
+ }
+ var has_hyphenated_non_dropping_particle = hasJoiningPunctuation(non_dropping_particle);
var blob, merged, first, second;
if (romanesque === 0) {
blob = this._join([non_dropping_particle, family, given], "");
@@ -9508,6 +9725,10 @@ CSL.NameOutput.prototype.getStaticOrder = function (name, refresh) {
}
CSL.NameOutput.prototype._splitInstitution = function (value, v, i) {
var ret = {};
+ if (!value.literal && value.family) {
+ value.literal = value.family;
+ delete value.family;
+ }
var splitInstitution = value.literal.replace(/\s*\|\s*/g, "|");
splitInstitution = splitInstitution.split("|");
if (this.institution.strings.form === "short" && this.state.sys.getAbbreviation) {
@@ -9852,11 +10073,9 @@ CSL.Node.names = {
}
if (this.tokentype === CSL.SINGLETON) {
state.build.names_variables.push(this.variables);
- for (var i = 0, ilen = this.variables.length; i < ilen; i += 1) {
- state.build.name_label[this.variables[i]] = state.build.name_label[state.build.names_variables.slice(0)[0]];
- }
func = function (state, Item, item) {
- state.nameOutput.reinit(this);
+ var labelVariable = state.nameOutput.labelVariable;
+ state.nameOutput.reinit(this, labelVariable);
};
this.execs.push(func);
}
@@ -10247,7 +10466,7 @@ CSL.Node.text = {
func = function (state, Item, item) {
var gender = state.opt.gender[Item.type];
var term = this.strings.term;
- term = state.getTerm(term, form, plural, gender, false, this.default_locale);
+ term = state.getTerm(term, form, plural, gender, CSL.TOLERANT, this.default_locale);
var myterm;
if (term !== "") {
state.tmp.group_context.tip.term_intended = true;
@@ -10276,6 +10495,9 @@ CSL.Node.text = {
state.build.plural = false;
} else if (this.variables_real.length) {
func = function (state, Item, item) {
+ if (this.variables_real[0] !== "locator") {
+ state.tmp.have_collapsed = false;
+ }
var parallel_variable = this.variables[0];
if (parallel_variable === "title"
&& (form === "short" || Item["title-short"])) {
@@ -11334,7 +11556,7 @@ CSL.Attributes["@second-field-align"] = function (state, arg) {
};
CSL.Attributes["@hanging-indent"] = function (state, arg) {
if (arg === "true") {
- state[this.name].opt.hangingindent = 2;
+ state[this.name].opt.hangingindent = true;
}
};
CSL.Attributes["@line-spacing"] = function (state, arg) {
@@ -11440,7 +11662,9 @@ CSL.Attributes["@reverse-order"] = function (state, arg) {
}
};
CSL.Attributes["@display"] = function (state, arg) {
- state.opt.using_display = true;
+ if (state.bibliography.tokens.length === 2) {
+ state.opt.using_display = true;
+ }
this.strings.cls = arg;
};
CSL.Stack = function (val, literal) {
@@ -12026,37 +12250,14 @@ CSL.Transform = function (state) {
this.getTextSubField = getTextSubField;
function abbreviate(state, Item, altvar, basevalue, myabbrev_family, use_field) {
var value;
+ myabbrev_family = CSL.FIELD_CATEGORY_REMAP[myabbrev_family];
if (!myabbrev_family) {
return basevalue;
}
var variable = myabbrev_family;
- var noHints = false;
- if (["title", "title-short"].indexOf(variable) > -1 && !Item.jurisdiction) {
- noHints = true;
- }
- if (CSL.NUMERIC_VARIABLES.indexOf(myabbrev_family) > -1) {
- myabbrev_family = "number";
- }
- if (myabbrev_family === "jurisdiction") {
- if (state.opt.suppressedJurisdictions[Item.jurisdiction]) {
- return "";
- }
- }
- if (["publisher-place", "event-place", "jurisdiction", "archive-place", "language-name", "language-name-original"].indexOf(myabbrev_family) > -1) {
- myabbrev_family = "place";
- }
- if (["publisher", "authority"].indexOf(myabbrev_family) > -1) {
- myabbrev_family = "institution-part";
- }
- if (["genre", "event", "medium", "title-short"].indexOf(myabbrev_family) > -1) {
- myabbrev_family = "title";
- }
- if (["archive"].indexOf(myabbrev_family) > -1) {
- myabbrev_family = "collection-title";
- }
value = "";
if (state.sys.getAbbreviation) {
- var jurisdiction = state.transform.loadAbbreviation(Item.jurisdiction, myabbrev_family, basevalue, Item.type, noHints);
+ var jurisdiction = state.transform.loadAbbreviation(Item.jurisdiction, myabbrev_family, basevalue, Item.type, true);
if (state.transform.abbrevs[jurisdiction][myabbrev_family] && basevalue && state.sys.getAbbreviation) {
if (state.transform.abbrevs[jurisdiction][myabbrev_family][basevalue]) {
value = state.transform.abbrevs[jurisdiction][myabbrev_family][basevalue].replace("{stet}",basevalue);
@@ -12105,11 +12306,16 @@ CSL.Transform = function (state) {
}
return ret;
};
- function getTextSubField(Item, field, locale_type, use_default, stopOrig) {
+ function getTextSubField (Item, field, locale_type, use_default, stopOrig) {
var m, lst, opt, o, oo, pos, key, ret, len, myret, opts;
var usedOrig = stopOrig;
+ var usingOrig = false;
if (!Item[field]) {
- return {name:"", usedOrig:stopOrig};
+ return {
+ name:"",
+ usedOrig:stopOrig,
+ token: CSL.Util.cloneToken(this)
+ };
}
ret = {name:"", usedOrig:stopOrig,locale:getFieldLocale(Item,field)};
opts = state.opt[locale_type];
@@ -12122,9 +12328,11 @@ CSL.Transform = function (state) {
ret = {name:Item[field], usedOrig:false, locale:getFieldLocale(Item,field)};
}
hasVal = true;
+ usingOrig = true;
} else if (use_default && ("undefined" === typeof opts || opts.length === 0)) {
var ret = {name:Item[field], usedOrig:true, locale:getFieldLocale(Item,field)};
hasVal = true;
+ usingOrig = true;
}
if (!hasVal) {
for (var i = 0, ilen = opts.length; i < ilen; i += 1) {
@@ -12132,7 +12340,7 @@ CSL.Transform = function (state) {
o = opt.split(/[\-_]/)[0];
if (opt && Item.multi && Item.multi._keys[field] && Item.multi._keys[field][opt]) {
ret.name = Item.multi._keys[field][opt];
- ret.locale = o;
+ ret.locale = opt;
if (field === 'jurisdiction') jurisdictionName = ret.name;
break;
} else if (o && Item.multi && Item.multi._keys[field] && Item.multi._keys[field][o]) {
@@ -12144,19 +12352,27 @@ CSL.Transform = function (state) {
}
if (!ret.name && use_default) {
ret = {name:Item[field], usedOrig:true, locale:getFieldLocale(Item,field)};
+ usingOrig = true;
}
}
- if (field === 'jurisdiction' && CSL.getSuppressedJurisdictionName) {
- if (ret.name && !jurisdictionName) {
- jurisdictionName = state.sys.getHumanForm(Item[field]);
- }
- if (jurisdictionName) {
- ret.name = CSL.getSuppressedJurisdictionName.call(state, Item[field], jurisdictionName);
+ ret.token = CSL.Util.cloneToken(this);
+ if (state.sys.getHumanForm && field === 'jurisdiction' && ret.name) {
+ ret.name = CSL.getJurisdictionNameAndSuppress(state, Item[field], jurisdictionName);
+ } else if (["title", "container-title"].indexOf(field) > -1) {
+ if (!usedOrig
+ && (!ret.token.strings["text-case"]
+ || ret.token.strings["text-case"] === "sentence"
+ || ret.token.strings["text-case"] === "normal")) {
+ var locale = usingOrig ? false : ret.locale;
+ var seg = field.slice(0,-5);
+ var sentenceCase = ret.token.strings["text-case"] === "sentence" ? true : false;
+ ret.name = CSL.titlecaseSentenceOrNormal(state, Item, seg, locale, sentenceCase);
+ delete ret.token.strings["text-case"];
}
}
return ret;
}
- function loadAbbreviation(jurisdiction, category, orig, itemType, noHints) {
+ function loadAbbreviation(jurisdiction, category, orig, itemType) {
var pos, len;
if (!jurisdiction) {
jurisdiction = "default";
@@ -12165,30 +12381,15 @@ CSL.Transform = function (state) {
if (!state.transform.abbrevs[jurisdiction]) {
state.transform.abbrevs[jurisdiction] = new state.sys.AbbreviationSegments();
}
+ if (!state.transform.abbrevs[jurisdiction][category]) {
+ state.transform.abbrevs[jurisdiction][category] = {};
+ }
return jurisdiction;
}
if (state.sys.getAbbreviation) {
- var tryList = ['default'];
- if (jurisdiction !== 'default') {
- var workLst = jurisdiction.split(":");
- for (var i=0, ilen=workLst.length; i < ilen; i += 1) {
- tryList.push(workLst.slice(0,i+1).join(":"));
- }
- }
- var found = false;
- for (var i=tryList.length - 1; i > -1; i += -1) {
- if (!state.transform.abbrevs[tryList[i]]) {
- state.transform.abbrevs[tryList[i]] = new state.sys.AbbreviationSegments();
- }
- if (!state.transform.abbrevs[tryList[i]][category][orig]) {
- state.sys.getAbbreviation(state.opt.styleID, state.transform.abbrevs, tryList[i], category, orig, itemType, noHints);
- }
- if (!found && state.transform.abbrevs[tryList[i]][category][orig]) {
- if (i < tryList.length) {
- state.transform.abbrevs[jurisdiction][category][orig] = state.transform.abbrevs[tryList[i]][category][orig];
- }
- found = true;
- }
+ jurisdiction = state.sys.getAbbreviation(state.opt.styleID, state.transform.abbrevs, jurisdiction, category, orig, itemType, true);
+ if (!jurisdiction) {
+ jurisdiction = "default";
}
}
return jurisdiction;
@@ -12262,9 +12463,10 @@ CSL.Transform = function (state) {
}
return null;
}
- var res = getTextSubField(Item, variables[0], slot.primary, true);
+ var res = getTextSubField.call(this, Item, variables[0], slot.primary, true);
primary = res.name;
primary_locale = res.locale;
+ var primary_tok = res.token;
var primaryUsedOrig = res.usedOrig;
if (publisherCheck(this, Item, primary, myabbrev_family)) {
return null;
@@ -12272,14 +12474,16 @@ CSL.Transform = function (state) {
secondary = false;
tertiary = false;
if (slot.secondary) {
- res = getTextSubField(Item, variables[0], slot.secondary, false, res.usedOrig);
+ res = getTextSubField.call(this, Item, variables[0], slot.secondary, false, res.usedOrig);
secondary = res.name;
secondary_locale = res.locale;
+ var secondary_tok = res.token;
}
if (slot.tertiary) {
- res = getTextSubField(Item, variables[0], slot.tertiary, false, res.usedOrig);
+ res = getTextSubField.call(this, Item, variables[0], slot.tertiary, false, res.usedOrig);
tertiary = res.name;
tertiary_locale = res.locale;
+ var tertiary_tok = res.token;
}
if (myabbrev_family) {
primary = abbreviate(state, Item, alternative_varname, primary, myabbrev_family, true);
@@ -12289,8 +12493,6 @@ CSL.Transform = function (state) {
secondary = abbreviate(state, Item, false, secondary, myabbrev_family, true);
tertiary = abbreviate(state, Item, false, tertiary, myabbrev_family, true);
}
- var template_tok = CSL.Util.cloneToken(this);
- var primary_tok = CSL.Util.cloneToken(this);
var primaryPrefix;
if (slot.primary === "locale-translit") {
primaryPrefix = state.opt.citeAffixes[langPrefs][slot.primary].prefix;
@@ -12318,7 +12520,6 @@ CSL.Transform = function (state) {
primary_tok.strings.suffix = primary_tok.strings.suffix.replace(/[ .,]+$/,"");
state.output.append(primary, primary_tok);
if (secondary) {
- secondary_tok = CSL.Util.cloneToken(template_tok);
secondary_tok.strings.prefix = state.opt.citeAffixes[langPrefs][slot.secondary].prefix;
secondary_tok.strings.suffix = state.opt.citeAffixes[langPrefs][slot.secondary].suffix;
if (!secondary_tok.strings.prefix) {
@@ -12346,7 +12547,6 @@ CSL.Transform = function (state) {
}
}
if (tertiary) {
- tertiary_tok = CSL.Util.cloneToken(template_tok);
tertiary_tok.strings.prefix = state.opt.citeAffixes[langPrefs][slot.tertiary].prefix;
tertiary_tok.strings.suffix = state.opt.citeAffixes[langPrefs][slot.tertiary].suffix;
if (!tertiary_tok.strings.prefix) {
@@ -12645,7 +12845,7 @@ CSL.Util.fixDateNode = function (parent, pos, node) {
this.cslXml.deleteNodeByNameAttribute(datexml, 'day');
} else if ("month-day" === this.cslXml.getAttributeValue(node, "date-parts")) {
var childNodes = this.cslXml.children(datexml);
- for (var i=1,ilen=childNodes.length;i", "", "italics", "@font-style", ["italic", "normal","normal"], true],
- ["", "", "bold", "@font-weight", ["bold", "normal","normal"], true],
- ["", "", "superscript", "@vertical-align", ["sup", "sup","baseline"], true],
- ["", "", "subscript", "@vertical-align", ["sub", "sub","baseline"], true],
- ["", "", "smallcaps", "@font-variant", ["small-caps", "small-caps","normal"], true],
- ["", "", "smallcaps", "@font-variant", ["small-caps", "normal","normal"], true],
- ["", "", "passthrough", "@passthrough", ["true", "true","true"], true],
- ["", "", "passthrough", "@passthrough", ["true", "true","true"], true],
- ['"', '"', "quotes", "@quotes", ["true", "inner","true"], "'"],
- [" '", "'", "quotes", "@quotes", ["inner", "true","true"], '"']
- ];
- for (pos = 0; pos < 2; pos += 1) {
- p = ["-", "-inner-"][pos];
- entry = [];
- var openq = state.getTerm(("open" + p + "quote"));
- entry.push(openq);
- this.quotechars.push(openq);
- var closeq = state.getTerm(("close" + p + "quote"));
- entry.push(closeq);
- this.quotechars.push(closeq);
- entry.push(("quote" + "s"));
- entry.push(("@" + "quote" + "s"));
- if ("-" === p) {
- entry.push(["true", "inner"]);
- } else {
- entry.push(["inner", "true"]);
- }
- entry.push(true);
- if ("-" === p) {
- entry.push(state.getTerm(("close-inner-quote")));
- } else {
- entry.push(state.getTerm(("close-quote")));
- }
- tagdefs.push(entry);
- }
- allTags = function (tagdefs) {
- ret = [];
- len = tagdefs.length;
- for (pos = 0; pos < len; pos += 1) {
- def = tagdefs[pos];
- if (ret.indexOf(def[0]) === -1) {
- esc = "";
- if (["(", ")", "[", "]"].indexOf(def[0]) > -1) {
- esc = "\\";
- }
- ret.push(esc + def[0]);
+CSL.Util.FlipFlopper = function(state) {
+ this.processTags = processTags;
+ var _nestingState = [];
+ var _nestingData = {
+ "": {
+ type: "nocase",
+ opener: "",
+ closer: "",
+ attr: null,
+ outer: null,
+ flipflop: null
+ },
+ "": {
+ type: "nodecor",
+ opener: "",
+ closer: "",
+ attr: "@class",
+ outer: "nodecor",
+ flipflop: {
+ "nodecor": "nodecor"
}
- if (ret.indexOf(def[1]) === -1) {
- esc = "";
- if (["(", ")", "[", "]"].indexOf(def[1]) > -1) {
- esc = "\\";
- }
- ret.push(esc + def[1]);
+ },
+ "": {
+ type: "tag",
+ opener: "",
+ closer: "",
+ attr: "@font-variant",
+ outer: "small-caps",
+ flipflop: {
+ "small-caps": "normal",
+ "normal": "small-caps"
+ }
+ },
+ "": {
+ type: "tag",
+ opener: "",
+ closer: "",
+ attr: "@font-variant",
+ outer: "small-caps",
+ flipflop: {
+ "small-caps": "normal",
+ "normal": "small-caps"
+ }
+ },
+ "": {
+ type: "tag",
+ opener: "",
+ closer: "",
+ attr: "@font-style",
+ outer: "italic",
+ flipflop: {
+ "italic": "normal",
+ "normal": "italic"
+ }
+ },
+ "": {
+ type: "tag",
+ opener: "",
+ closer: "",
+ attr: "@font-weight",
+ outer: "bold",
+ flipflop: {
+ "bold": "normal",
+ "normal": "bold"
+ }
+ },
+ "": {
+ type: "tag",
+ opener: "",
+ closer: "",
+ attr: "@vertical-align",
+ outer: "sup",
+ flipflop: {
+ "sub": "sup",
+ "sup": "sup"
+ }
+ },
+ "": {
+ type: "tag",
+ opener: "",
+ closer: "",
+ attr: "@vertical-align",
+ outer: "sub",
+ flipflop: {
+ "sup": "sub",
+ "sub": "sub"
+ }
+ },
+ " \"": {
+ type: "quote",
+ opener: " \"",
+ closer: "\"",
+ attr: "@quotes",
+ outer: "true",
+ flipflop: {
+ "true": "inner",
+ "inner": "true"
+ }
+ },
+ " \'": {
+ type: "quote",
+ opener: " \'",
+ closer: "\'",
+ attr: "@quotes",
+ outer: "inner",
+ flipflop: {
+ "true": "inner",
+ "inner": "true"
+ }
+ }
+ }
+ _nestingData["(\""] = _nestingData[" \""]
+ _nestingData["(\'"] = _nestingData[" \'"]
+ var localeOpenQuote = state.getTerm("open-quote");
+ var localeCloseQuote = state.getTerm("close-quote");
+ var localeOpenInnerQuote = state.getTerm("open-inner-quote");
+ var localeCloseInnerQuote = state.getTerm("close-inner-quote");
+ if (localeOpenQuote && localeCloseQuote && [" \""," \'","\"","\'"].indexOf(localeOpenQuote) === -1) {
+ _nestingData[localeOpenQuote] = JSON.parse(JSON.stringify(_nestingData[" \""]));
+ _nestingData[localeOpenQuote].opener = localeOpenQuote;
+ _nestingData[localeOpenQuote].closer = localeCloseQuote;
+ }
+ if (localeOpenInnerQuote && localeCloseInnerQuote && [" \""," \'","\"","\'"].indexOf(localeOpenInnerQuote) === -1) {
+ _nestingData[localeOpenInnerQuote] = JSON.parse(JSON.stringify(_nestingData[" \'"]));
+ _nestingData[localeOpenInnerQuote].opener = localeOpenInnerQuote;
+ _nestingData[localeOpenInnerQuote].closer = localeCloseInnerQuote;
+ }
+ var _nestingQuoteReverse = function() {
+ var ret = {};
+ for (var key of Object.keys(_nestingData)) {
+ if (_nestingData[key].type === "quote") {
+ ret[_nestingData[key].closer] = _nestingData[key];
}
}
return ret;
- };
- allTagsLst = allTags(tagdefs);
- lst = [];
- for (pos = 0, len = allTagsLst.length; pos < len; pos += 1) {
- if (allTagsLst[pos]) {
- lst.push(allTagsLst[pos]);
+ }();
+ var _nestingDataAttr = function() {
+ var ret = {};
+ for (var key of Object.keys(_nestingData)) {
+ if (_nestingData[key].type === "nocase") continue;
+ var attr = _nestingData[key].attr;
+ var outer = _nestingData[key].outer;
+ var inner = _nestingData[key].flipflop[_nestingData[key].outer];
+ ret[attr + "/" + outer] = _nestingData[key];
+ ret[attr + "/" + inner] = _nestingData[key];
}
- }
- allTagsLst = lst.slice();
- this.allTagsRexMatch = new RegExp("(" + allTagsLst.join("|") + ")", "g");
- this.allTagsRexSplit = new RegExp("(?:" + allTagsLst.join("|") + ")");
- makeHashes = function (tagdefs) {
- closeTags = {};
- flipTags = {};
- openToClose = {};
- openToDecorations = {};
- okReverse = {};
- len = tagdefs.length;
- for (pos = 0; pos < len; pos += 1) {
- closeTags[tagdefs[pos][1]] = true;
- flipTags[tagdefs[pos][1]] = tagdefs[pos][5];
- openToClose[tagdefs[pos][0]] = tagdefs[pos][1];
- openToDecorations[tagdefs[pos][0]] = [tagdefs[pos][3], tagdefs[pos][4]];
- okReverse[tagdefs[pos][3]] = [tagdefs[pos][3], [tagdefs[pos][4][2], tagdefs[pos][1]]];
+ return ret;
+ }();
+ function _setOuterQuoteForm(quot) {
+ var flip = {
+ " \'": " \"",
+ " \"": " \'",
+ "(\"": "(\'",
+ "(\'": "(\""
}
- return [closeTags, flipTags, openToClose, openToDecorations, okReverse];
- };
- hashes = makeHashes(tagdefs);
- this.closeTagsHash = hashes[0];
- this.flipTagsHash = hashes[1];
- this.openToCloseHash = hashes[2];
- this.openToDecorations = hashes[3];
- this.okReverseHash = hashes[4];
-};
-CSL.Util.FlipFlopper.prototype.init = function (str, blob) {
- this.txt_esc = CSL.getSafeEscape(this.state);
- if (!blob) {
- this.strs = this.getSplitStrings(str);
- this.blob = new CSL.Blob();
- } else {
- this.blob = blob;
- this.strs = this.getSplitStrings(this.blob.blobs);
- this.blob.blobs = [];
+ _nestingData[quot].outer = "true";
+ _nestingData[flip[quot]].outer = "inner";
}
- this.blobstack = new CSL.Stack(this.blob);
-};
-CSL.Util.FlipFlopper.prototype._normalizeString = function (str) {
- var i, ilen;
- str = str.replace(/\s+'\s+/g," ’ ");
- if (str.indexOf(this.quotechars[0]) > -1) {
- var oldStr = null;
- while (str !== oldStr) {
- oldStr = str;
- for (i = 0, ilen = 2; i < ilen; i += 1) {
- if (this.quotechars[i + 2]) {
- str = str.split(this.quotechars[i + 2]).join(this.quotechars[0]);
- }
+ function _getNestingOpenerParams(opener) {
+ var openers = [];
+ var closer;
+ for (var key of Object.keys(_nestingData)) {
+ if (_nestingData[opener].type !== "quote" || !_nestingData[opener]) {
+ openers.push(key);
}
}
+ var ret = _nestingData[opener];
+ ret.opener = new RegExp("^(?:" + openers.map(function(str){return str.replace("(", "\\(")}).join("|") + ")");
+ return ret;
}
- if (str.indexOf(this.quotechars[1]) > -1) {
- for (i = 0, ilen = 2; i < ilen; i += 1) {
- if (this.quotechars[i + 4]) {
- if (i === 0 && this.quotechars[i + 4] !== this.quotechars[1]) {
- str = str.split(this.quotechars[i + 4]).join(" " + this.quotechars[1]);
- } else {
- str = str.split(this.quotechars[i + 4]).join(this.quotechars[1]);
- }
- }
+ var _nestingParams = function() {
+ var ret = {};
+ for (var key of Object.keys(_nestingData)) {
+ ret[key] = _getNestingOpenerParams(key);
+ }
+ return ret;
+ }()
+ var _tagRex = function() {
+ var openers = [];
+ var closers = [];
+ var vals = {};
+ for (var opener in _nestingParams) {
+ openers.push(opener);
+ vals[_nestingParams[opener].closer] = true;
+ }
+ for (var closer of Object.keys(vals)) {
+ closers.push(closer);
+ }
+ var all = openers.concat(closers).map(function(str){return str.replace("(", "\\(")}).join("|");
+ return {
+ matchAll: new RegExp("((?:" + all + "))", "g"),
+ splitAll: new RegExp("(?:" + all + ")", "g"),
+ open: new RegExp("(^(?:" + openers.map(function(str){return str.replace("(", "\\(")}).join("|") + ")$)"),
+ close: new RegExp("(^(?:" + closers.join("|") + ")$)"),
+ }
+ }();
+ function _nestingFix (tag, pos) {
+ return _pushNestingState(tag, pos);
+ }
+ function _pushNestingState(tag, pos) {
+ if (tag.match(_tagRex.open)) {
+ return _tryOpen(tag, pos);
+ } else {
+ return _tryClose(tag, pos);
}
}
- return str;
-};
-CSL.Util.FlipFlopper.prototype.getSplitStrings = function (str) {
- var strs, pos, len, newstr, head, tail, expected_closers, expected_openers, expected_flips, tagstack, badTagStack, posA, sameAsOpen, openRev, flipRev, tag, ibeenrunned, posB, wanted_closer, posC, sep, resplice, params, lenA, lenB, lenC, badTagPos, mx, myret;
- str = this._normalizeString(str);
- mx = str.match(this.allTagsRexMatch);
- strs = str.split(this.allTagsRexSplit);
- myret = [strs[0]];
- for (pos = 1, len = strs.length; pos < len; pos += 1) {
- myret.push(mx[pos - 1]);
- myret.push(strs[pos]);
- }
- strs = myret.slice();
- len = strs.length - 2;
- for (pos = len; pos > 0; pos += -2) {
- if (strs[(pos - 1)].slice((strs[(pos - 1)].length - 1)) === "\\") {
- newstr = strs[(pos - 1)].slice(0, (strs[(pos - 1)].length - 1)) + strs[pos] + strs[(pos + 1)];
- head = strs.slice(0, (pos - 1));
- tail = strs.slice((pos + 2));
- head.push(newstr);
- strs = head.concat(tail);
- }
- }
- expected_closers = [];
- expected_openers = [];
- expected_flips = [];
- tagstack = [];
- badTagStack = [];
- lenA = strs.length - 1;
- for (posA = 1; posA < lenA; posA += 2) {
- tag = strs[posA];
- if (this.closeTagsHash[tag]) {
- expected_closers.reverse();
- sameAsOpen = this.openToCloseHash[tag];
- openRev = expected_closers.indexOf(tag);
- flipRev = expected_flips.indexOf(tag);
- expected_closers.reverse();
- if (!sameAsOpen || (openRev > -1 && (openRev < flipRev || flipRev === -1))) {
- ibeenrunned = false;
- lenB = expected_closers.length - 1;
- for (posB = lenB; posB > -1; posB += -1) {
- ibeenrunned = true;
- wanted_closer = expected_closers[posB];
- if (tag === wanted_closer) {
- expected_closers.pop();
- expected_openers.pop();
- expected_flips.pop();
- tagstack.pop();
- break;
- }
- badTagStack.push(posA);
- }
- if (!ibeenrunned) {
- badTagStack.push(posA);
- }
- continue;
- }
- }
- if (this.openToCloseHash[tag]) {
- expected_closers.push(this.openToCloseHash[tag]);
- expected_openers.push(tag);
- expected_flips.push(this.flipTagsHash[tag]);
- tagstack.push(posA);
- }
- }
- lenC = expected_closers.length - 1;
- for (posC = lenC; posC > -1; posC += -1) {
- expected_closers.pop();
- expected_flips.pop();
- expected_openers.pop();
- badTagStack.push(tagstack.pop());
- }
- badTagStack.sort(
- function (a, b) {
- if (a < b) {
- return 1;
- } else if (a > b) {
- return -1;
- }
- return 0;
- }
- );
- len = badTagStack.length;
- for (pos = 0; pos < len; pos += 1) {
- badTagPos = badTagStack[pos];
- head = strs.slice(0, (badTagPos - 1));
- tail = strs.slice((badTagPos + 2));
- sep = strs[badTagPos];
- if (sep.length && sep[0] !== "<" && this.openToDecorations[sep] && this.quotechars.indexOf(sep.replace(/\s+/g,"")) === -1) {
- params = this.openToDecorations[sep];
- sep = this.state.fun.decorate[params[0]][params[1][0]](this.state);
- }
- resplice = strs[(badTagPos - 1)] + sep + strs[(badTagPos + 1)];
- head.push(resplice);
- strs = head.concat(tail);
- }
- len = strs.length;
- for (pos = 0; pos < len; pos += 2) {
- strs[pos] = strs[pos].split("'").join("\u2019");
- strs[pos] = strs[pos].split(" \u2019").join(" \u2019");
- }
- return strs;
-};
-CSL.Util.FlipFlopper.prototype.processTags = function () {
- var expected_closers, expected_openers, expected_flips, expected_rendering, str, posA, tag, prestr, newblob, blob, sameAsOpen, openRev, flipRev, posB, wanted_closer, newblobnest, param, fulldecor, level, decor, lenA, lenB, posC, lenC;
- expected_closers = [];
- expected_openers = [];
- expected_flips = [];
- expected_rendering = [];
- str = "";
- if (this.strs.length === 1) {
- this.blob.blobs = this.strs[0];
- } else if (this.strs.length > 2) {
- lenA = (this.strs.length - 1);
- for (posA = 1; posA < lenA; posA += 2) {
- tag = this.strs[posA];
- prestr = this.strs[(posA - 1)];
- if (prestr) {
- newblob = new CSL.Blob(prestr);
- blob = this.blobstack.value();
- blob.push(newblob);
- }
- if (this.closeTagsHash[tag]) {
- expected_closers.reverse();
- sameAsOpen = this.openToCloseHash[tag];
- openRev = expected_closers.indexOf(tag);
- flipRev = expected_flips.indexOf(tag);
- expected_closers.reverse();
- if (!sameAsOpen || (openRev > -1 && (openRev < flipRev || flipRev === -1))) {
- lenB = expected_closers.length;
- for (posB = lenB; posB > -1; posB += -1) {
- wanted_closer = expected_closers[posB];
- if (tag === wanted_closer) {
- expected_closers.pop();
- expected_openers.pop();
- expected_flips.pop();
- expected_rendering.pop();
- this.blobstack.pop();
- break;
- }
- }
- continue;
- }
- }
- if (this.openToCloseHash[tag]) {
- expected_closers.push(this.openToCloseHash[tag]);
- expected_openers.push(tag);
- expected_flips.push(this.flipTagsHash[tag]);
- blob = this.blobstack.value();
- newblobnest = new CSL.Blob();
- blob.push(newblobnest);
- param = this.addFlipFlop(newblobnest, this.openToDecorations[tag]);
- if (tag === "") {
- fulldecor = this.state[this.state.tmp.area].opt.topdecor.concat(this.blob.alldecor).concat([[["@quotes", "inner"]]]);
- lenB = fulldecor.length;
- for (posB = 0; posB < lenB; posB += 1) {
- level = fulldecor[posB];
- lenC = level.length;
- for (posC = 0; posC < lenC; posC += 1) {
- decor = level[posC];
- if (["@font-style", "@font-weight", "@font-variant"].indexOf(decor[0]) > -1) {
- param = this.addFlipFlop(newblobnest, this.okReverseHash[decor[0]]);
- }
- }
- }
- }
- expected_rendering.push(this.state.fun.decorate[param[0]][param[1]](this.state));
- this.blobstack.push(newblobnest);
- }
- }
- if (this.strs.length > 2) {
- str = this.strs[(this.strs.length - 1)];
- if (str) {
- blob = this.blobstack.value();
- newblob = new CSL.Blob(str);
- blob.push(newblob);
- }
- }
- }
- return this.blob;
-};
-CSL.Util.FlipFlopper.prototype.addFlipFlop = function (blob, fun) {
- var posA, posB, fulldecor, lenA, decorations, breakme, decor, posC, newdecor, lenC;
- posB = 0;
- fulldecor = this.state[this.state.tmp.area].opt.topdecor.concat(blob.alldecor).concat([[["@quotes", "inner"]]]);
- lenA = fulldecor.length;
- for (posA = 0; posA < lenA; posA += 1) {
- decorations = fulldecor[posA];
- breakme = false;
- lenC = decorations.length - 1;
- for (posC = lenC; posC > -1; posC += -1) {
- decor = decorations[posC];
- if (decor[0] === fun[0]) {
- if (decor[1] === fun[1][0]) {
- posB = 1;
- }
- breakme = true;
- break;
- }
- }
- if (breakme) {
- break;
- }
- }
- newdecor = [fun[0], fun[1][posB]];
- blob.decorations.reverse();
- blob.decorations.push(newdecor);
- blob.decorations.reverse();
- return newdecor;
-};
-CSL.Output.Formatters = {};
-CSL.getSafeEscape = function(state) {
- if (["bibliography", "citation"].indexOf(state.tmp.area) > -1) {
- var callbacks = [];
- if (state.opt.development_extensions.thin_non_breaking_space_html_hack && state.opt.mode === "html") {
- callbacks.push(function (txt) {
- return txt.replace(/\u202f/g, ' ');
+ function _tryOpen(tag, pos) {
+ var params = _nestingState[_nestingState.length - 1];
+ if (!params || tag.match(params.opener)) {
+ _nestingState.push({
+ type: _nestingParams[tag].type,
+ opener: _nestingParams[tag].opener,
+ closer: _nestingParams[tag].closer,
+ pos: pos
});
+ return false;
+ } else {
+ _nestingState.pop()
+ _nestingState.push({
+ type: _nestingParams[tag].type,
+ opener: _nestingParams[tag].opener,
+ closer: _nestingParams[tag].closer,
+ pos: pos
+ });
+ return {
+ fixtag: params.pos
+ };
}
- if (callbacks.length) {
- return function (txt) {
- for (var i = 0, ilen = callbacks.length; i < ilen; i += 1) {
- txt = callbacks[i](txt);
+ }
+ function _tryClose(tag, pos) {
+ var params = _nestingState[_nestingState.length - 1];
+ if (params && tag === params.closer) {
+ _nestingState.pop()
+ if (params.type === "nocase") {
+ return {
+ nocase: {
+ open: params.pos,
+ close: pos
+ }
}
- return CSL.Output.Formats[state.opt.mode].text_escape(txt);
+ } else {
+ return false;
}
} else {
- return CSL.Output.Formats[state.opt.mode].text_escape;
- }
- } else {
- return function (txt) { return txt; };
- }
-};
-CSL.Output.Formatters.passthrough = function (state, string) {
- return string;
-};
-CSL.Output.Formatters.lowercase = function (state, string) {
- var str = CSL.Output.Formatters.doppelString(string, CSL.TAG_USEALL);
- str.string = str.string.toLowerCase();
- return CSL.Output.Formatters.undoppelString(str);
-};
-CSL.Output.Formatters.uppercase = function (state, string) {
- var str = CSL.Output.Formatters.doppelString(string, CSL.TAG_USEALL);
- str.string = str.string.toUpperCase();
- return CSL.Output.Formatters.undoppelString(str);
-};
-CSL.Output.Formatters["capitalize-first"] = function (state, string) {
- var str = CSL.Output.Formatters.doppelString(string, CSL.TAG_ESCAPE);
- if (str.string.length) {
- str.string = str.string.slice(0, 1).toUpperCase() + str.string.substr(1);
- return CSL.Output.Formatters.undoppelString(str);
- } else {
- return "";
- }
-};
-CSL.Output.Formatters.sentence = function (state, string) {
- var str = CSL.Output.Formatters.doppelString(string, CSL.TAG_ESCAPE);
- str.string = str.string.slice(0, 1).toUpperCase() + str.string.substr(1).toLowerCase();
- return CSL.Output.Formatters.undoppelString(str);
-};
-CSL.Output.Formatters["capitalize-all"] = function (state, string) {
- var str = CSL.Output.Formatters.doppelString(string, CSL.TAG_ESCAPE);
- var strings = str.string.split(" ");
- for (var i = 0, ilen = strings.length; i < ilen; i += 1) {
- if (strings[i].length > 1) {
- if (state.opt.development_extensions.allow_force_lowercase) {
- strings[i] = strings[i].slice(0, 1).toUpperCase() + strings[i].substr(1).toLowerCase();
- } else {
- strings[i] = strings[i].slice(0, 1).toUpperCase() + strings[i].substr(1);
- }
- } else if (strings[i].length === 1) {
- strings[i] = strings[i].toUpperCase();
+ if (params) {
+ return {
+ fixtag: params.pos
+ };
+ } else {
+ return {
+ fixtag: pos
+ };
+ }
}
}
- str.string = strings.join(" ");
- return CSL.Output.Formatters.undoppelString(str);
-};
-CSL.Output.Formatters.title = function (state, string) {
- var str, words, isAllUpperCase, newString, lastWordIndex, previousWordIndex, upperCaseVariant, lowerCaseVariant, pos, skip, notfirst, notlast, aftercolon, len, idx, tmp, skipword, ppos, mx, lst, myret;
- var SKIP_WORDS = state.locale[state.opt.lang].opts["skip-words"];
- if (!string) {
- return "";
+ function _doppelString(str) {
+ str = str.replace(/(]*(>)/g, "$1 $2$3;\"$4");
+ str = str.replace(/(]*(>)/g, "$1 $2$3");
+ var match = str.match(_tagRex.matchAll);
+ if (!match) {
+ return {
+ tags: [],
+ strings: [str]
+ };
+ }
+ var split = str.split(_tagRex.splitAll);
+ return {
+ tags: match,
+ strings: split
+ }
}
- var doppel = CSL.Output.Formatters.doppelString(string, CSL.TAG_ESCAPE, SKIP_WORDS);
- function capitalise (word, force) {
- var m = word.match(/([:?!]+\s+|-|^)((?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))(.*)/);
+ function _undoppelString(obj) {
+ var lst = obj.strings.slice(-1);
+ for (var i=obj.tags.length-1; i>-1; i+=-1) {
+ lst.push(obj.tags[i]);
+ lst.push(obj.strings[i]);
+ }
+ lst.reverse();
+ return lst.join("|");
+ }
+ var _TagReg = function(blob) {
+ this.set = set;
+ this.pair = pair;
+ this.pop = pop;
+ _stack = [];
+ function set(tag) {
+ var attr = _nestingData[tag].attr;
+ var decor = null;
+ for (var i=_stack.length-1;i>-1;i--) {
+ var _decor = _stack[i];
+ if (_decor[0] === attr) {
+ decor = _decor;
+ break;
+ }
+ }
+ if (!decor) {
+ var allTheDecor = [state[state.tmp.area].opt.layout_decorations].concat(blob.alldecor)
+ outer:
+ for (var i=allTheDecor.length-1;i>-1;i--) {
+ var decorset = allTheDecor[i];
+ if (!decorset) continue;
+ for (var j=decorset.length-1;j>-1;j--) {
+ var _decor = decorset[j];
+ if (_decor[0] === attr) {
+ decor = _decor;
+ break outer;
+ }
+ }
+ }
+ }
+ if (!decor) {
+ decor = [attr, _nestingData[tag].outer];
+ } else {
+ decor = [attr, _nestingData[tag].flipflop[decor[1]]];
+ }
+ _stack.push(decor);
+ }
+ function pair() {
+ return _stack[_stack.length-1];
+ }
+ function pop() {
+ _stack.pop();
+ }
+ }
+ function _apostropheForce(tag, str) {
+ if (tag === "\'") {
+ if (str && str.match(/^[^\.\?\:\;\ ]/)) {
+ return true;
+ }
+ } else if (tag === " \'" && str && str.match(/^[\ ]/)) {
+ return true;
+ }
+ return false;
+ }
+ function _undoppelToQueue(blob, doppel) {
+ var TOP = blob;
+ var firstString = true;
+ var tagReg = new _TagReg(blob);
+ blob.blobs = [];
+ function Stack (blob) {
+ this.stack = [blob];
+ this.latest = blob;
+ this.addStyling = function(str, decor) {
+ if (firstString) {
+ if (str.slice(0, 1) === " ") {
+ str = str.slice(1);
+ }
+ if (str.slice(0, 1) === " ") {
+ str = str.slice(1);
+ }
+ firstString = false;
+ }
+ this.latest = this.stack[this.stack.length-1];
+ if (decor) {
+ if ("string" === typeof this.latest.blobs) {
+ var child = new CSL.Blob();
+ child.blobs = this.latest.blobs;
+ child.alldecor = this.latest.alldecor.slice();
+ this.latest.blobs = [child];
+ }
+ var tok = new CSL.Token();
+ var newblob = new CSL.Blob(null, tok);
+ newblob.alldecor = this.latest.alldecor.slice();
+ if (decor[0] === "@class" && decor[1] === "nodecor") {
+ var newdecorset = [];
+ var seen = {};
+ var allTheDecor = [state[state.tmp.area].opt.layout_decorations].concat(newblob.alldecor)
+ for (var i=allTheDecor.length-1;i>-1;i--) {
+ var _decorset = allTheDecor[i];
+ if (!_decorset) continue;
+ for (var j=_decorset.length-1;j>-1;j--) {
+ var _olddecor = _decorset[j];
+ if (["@font-weight", "@font-style", "@font-variant"].indexOf(_olddecor[0]) > -1
+ && !seen[_olddecor[0]]) {
+ if (decor[1] !== "normal") {
+ newblob.decorations.push([_olddecor[0], "normal"]);
+ newdecorset.push([_olddecor[0], "normal"])
+ }
+ seen[_olddecor[0]] = true;
+ }
+ }
+ }
+ newblob.alldecor.push(newdecorset);
+ } else {
+ newblob.decorations.push(decor);
+ newblob.alldecor.push([decor]);
+ }
+ this.latest.blobs.push(newblob);
+ this.stack.push(newblob);
+ this.latest = newblob;
+ if (str) {
+ var tok = new CSL.Token();
+ var newblob = new CSL.Blob(null, tok);
+ newblob.blobs = str;
+ newblob.alldecor = this.latest.alldecor.slice();
+ this.latest.blobs.push(newblob);
+ }
+ } else {
+ if (str) {
+ var child = new CSL.Blob();
+ child.blobs = str;
+ child.alldecor = this.latest.alldecor.slice();
+ this.latest.blobs.push(child);
+ }
+ }
+ }
+ this.popStyling = function() {
+ this.stack.pop();
+ }
+ };
+ var stack = new Stack(blob);
+ if (doppel.strings.length) {
+ stack.addStyling(doppel.strings[0]);
+ }
+ for (var i=0,ilen=doppel.tags.length;i -1) {
+ if (tag.match(_tagRex.close)
+ && tag === "\'") {
+ doppel.strings[i+1] = "\u2019" + doppel.strings[i+1];
+ doppel.tags[i] = "";
+ } else {
+ doppel.strings[tagInfo.fixtag+1] = doppel.tags[tagInfo.fixtag] + doppel.strings[tagInfo.fixtag+1];
+ doppel.tags[tagInfo.fixtag] = "";
+ }
+ if (_nestingState.length > 0) {
+ _nestingState.pop();
+ } else {
+ break;
+ }
+ } else if (tagInfo.nocase) {
+ doppel.tags[tagInfo.nocase.open] = "";
+ doppel.tags[tagInfo.nocase.close] = "";
+ break;
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (tagInfo && (tagInfo.fixtag|| tagInfo.fixtag === 0)) {
+ doppel.strings[i+1] = doppel.tags[i] + doppel.strings[i+1];
+ doppel.tags[i] = "";
+ }
+ }
+ }
+ for (var i=_nestingState.length-1;i>-1;i--) {
+ var tagPos = _nestingState[i].pos
+ var tag = doppel.tags[tagPos];
+ if (tag === " \'" || tag === "\'") {
+ doppel.strings[tagPos+1] = " \u2019" + doppel.strings[tagPos+1];
+ doppel.tags[tagPos] = "";
+ } else {
+ doppel.strings[tagPos+1] = doppel.tags[tagPos] + doppel.strings[tagPos+1];
+ doppel.tags[tagPos] = "";
+ }
+ _nestingState.pop();
+ }
+ for (var i=doppel.tags.length-1;i>-1;i--) {
+ if (!doppel.tags[i]) {
+ doppel.tags = doppel.tags.slice(0,i).concat(doppel.tags.slice(i+1));
+ doppel.strings[i] = doppel.strings[i] + doppel.strings[i+1];
+ doppel.strings = doppel.strings.slice(0,i+1).concat(doppel.strings.slice(i+2));
+ }
+ }
+ for (var i=0,ilen=doppel.tags.length;i -1) {
+ if (!quoteFormSeen) {
+ _setOuterQuoteForm(tag);
+ quoteFormSeen = true;
+ }
+ doppel.strings[i] += tag.slice(0, 1);
+ }
+ }
+ _undoppelToQueue(blob, doppel);
+ }
+}
+CSL.Output.Formatters = new function () {
+ this.passthrough = passthrough;
+ this.lowercase = lowercase;
+ this.uppercase = uppercase;
+ this.sentence = sentence;
+ this.title = title;
+ this["capitalize-first"] = capitalizeFirst;
+ this["capitalize-all"] = capitalizeAll;
+ var rexStr = "(?:\u2018|\u2019|\u201C|\u201D| \"| \'|\"|\'|[-\–\—\/.,;?!:]|\\[|\\]|\\(|\\)|||<\/span>|<\/?(?:i|sc|b|sub|sup)>)";
+ tagDoppel = new CSL.Doppeler(rexStr, function(str) {
+ return str.replace(/(]*(>)/g, "$1 $2$3").replace(/(]*(>)/g, "$1 $2 $3;$4$5");
+ });
+ wordDoppel = new CSL.Doppeler("(?:[\u0020\u00A0\u2000-\u200B\u205F\u3000]+)");
+ var _tagParams = {
+ "": "",
+ "": "",
+ "": ""
+ }
+ function _capitalise (word, force) {
+ var m = word.match(/(^\s*)((?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))(.*)/);
if (m && !(m[2].match(/^[\u0370-\u03FF]$/) && !m[3])) {
return m[1] + m[2].toUpperCase() + m[3];
}
return word;
}
- function splitme (str, rex) {
- var m = str.match(rex);
- if (m) {
- var splits = str.split(rex);
- res = [splits[0]];
- for (var i=0; i -1 ? true : false;
+ if (isOpener) {
+ return tryOpen(tag, pos);
+ } else {
+ return tryClose(tag, pos);
+ }
}
- }
- if (!lst[0] && lst[1]) {
- lst[1] = capitalise(lst[1]);
- }
- if (lst.length > 2 && !lst[lst.length-1]) {
- lst[lst.length-2] = capitalise(lst[lst.length-2]);
- }
- for (var i=0,ilen=lst.length;i 0 && tag === config.quoteState[config.quoteState.length - 1].closer) {
+ config.quoteState.pop()
+ } else {
+ return pos;
+ }
+ }
+ if (config.doppel.strings.length && config.doppel.strings[0].trim()) {
+ config.doppel.strings[0] = config.capitaliseWords(config.doppel.strings[0], 0, config.doppel.tags[0]);
+ }
+ for (var i=0,ilen=config.doppel.tags.length;i -1; j += -1) {
- if (SKIP_WORDS.indexOf(fld[j].toLowerCase()) > -1) {
- toEnd.push(fld.pop());
- } else {
- break;
- }
- }
- fld.reverse();
- var start = fld.join(" ");
- var end = toEnd.join(" ");
- if ("drop" === drop_or_demote || !end) {
- fld = start;
- } else if ("demote" === drop_or_demote) {
- fld = [start, end].join(", ");
+ if (config.lastWordPos) {
+ var lastWords = wordDoppel.split(config.doppel.strings[config.lastWordPos.strings]);
+ var lastWord = _capitalise(lastWords.strings[config.lastWordPos.words]);
+ lastWords.strings[config.lastWordPos.words] = lastWord;
+ config.doppel.strings[config.lastWordPos.strings] = wordDoppel.join(lastWords);
}
+ return tagDoppel.join(config.doppel);
}
- return fld;
-};
+ function passthrough (state, str) {
+ return str;
+ }
+ function lowercase(state, string) {
+ var config = {
+ quoteState: null,
+ capitaliseWords: function(str) {
+ var words = str.split(" ");
+ for (var i=0,ilen=words.length;i 1 && !word.toLowerCase().match(config.skipWordsRex)) {
+ words[j] = _capitalise(words[j]);
+ } else if (j === (words.length - 1) && followingTag === "-") {
+ words[j] = _capitalise(words[j]);
+ } else if (config.isFirst) {
+ words[j] = _capitalise(words[j]);
+ } else if (config.afterPunct) {
+ words[j] = _capitalise(words[j]);
+ }
+ config.afterPunct = false;
+ config.isFirst = false;
+ config.lastWordPos = {
+ strings: i,
+ words: j
+ }
+ }
+ str = wordDoppel.join(wordle);
+ }
+ return str;
+ },
+ skipWordsRex: state.locale[state.opt.lang].opts["skip-words-regexp"],
+ tagState: [],
+ afterPunct: false,
+ isFirst: true
+ }
+ return _textcaseEngine(config, string);
+ }
+ function capitalizeFirst(state, string) {
+ var config = {
+ quoteState: [],
+ capitaliseWords: function(str) {
+ var words = str.split(" ");
+ for (var i=0,ilen=words.length;i