http://forums.zotero.org/discussion/2107/bibtex-book-chapter-title/
Unfortunately there is no way to do this currently with the bibtex
exporter. The bibtex exporter currently maps one zotero type to one
bibtex type.
Devs, I will post to the dev-list a modification of bibtex export
which creates two type maps, one for bibtex2zotero & one for
zotero2bibtex. The zotero2bibtex can either have strings or functions.
If the value is a function the function is called with the zotero item
as its argument, and returns the bibtex type. The means that the
function can then check features of the item to decide what bibtex
type it should be. In this case it checks if the item has an author &
an editor, if so, its incollection, otherwise inbook.
This would require more work for the other way round, since the whole
bibtex record would need to be read before the type was decided.
---snip----
var fieldMap = {
address:"place",
chapter:"section",
edition:"edition",
// number:"issue",
type:"type",
series:"series",
title:"title",
volume:"volume",
copyright:"rights",
isbn:"ISBN",
issn:"ISSN",
location:"archiveLocation",
url:"url",
doi:"DOI",
"abstract":"abstractNote",
};
var inputFieldMap = {
booktitle :"publicationTitle",
school:"publisher",
publisher:"publisher"
};
var zotero2bibtexTypeMap = {
"book":"book",
"bookSection": function (item) {
var hasAuthor = false;
var hasEditor = false;
for each(var creator in item.creators) {
if (creator.creatorType == "editor") { hasEditor = true; }
if (creator.creatorType == "author") { hasAuthor = true; }
}
if (hasAuthor && hasEditor) { return "incollection"; }
return "inbook";
},
"journalArticle":"article",
"magazineArticle":"article",
"newspaperArticle":"article",
"thesis":"phdthesis",
"letter":"misc",
"manuscript":"unpublished",
"interview":"misc",
"film":"misc",
"artwork":"misc",
"webpage":"misc",
"conferencePaper":"inproceedings"
};
var bibtex2zoteroTypeMap = {
"book":"book", // or booklet, proceedings
"inbook":"bookSection",
"incollection":"bookSection",
"article":"journalArticle", // or magazineArticle or newspaperArticle
"phdthesis":"thesis",
"unpublished":"manuscript",
"inproceedings":"conferencePaper", // check for "conference" also
"techreport":"report",
"booklet":"book",
"incollection":"bookSection",
"manual":"book",
"mastersthesis":"thesis",
"misc":"book",
"proceedings":"conference"
};
/*
* three-letter month abbreviations. i assume these are the same ones
that the
* docs say are defined in some appendix of the LaTeX book. (i don't
have the
* LaTeX book.)
*/
var months = ["jan", "feb", "mar", "apr", "may", "jun",
"jul", "aug", "sep", "oct", "nov", "dec"]
/*
* this is the character table for converting TeX to Unicode. sorry,
Czech
* speakers; you'll have to add your own (or stop using BibTeX!)
*/
var accentedCharacters = {
// grave accents
192:"\\`A", 224:"\\`a",
200:"\\`E", 232:"\\`e",
204:"\\`I", 236:"\\`i",
210:"\\`O", 242:"\\`o",
217:"\\`U", 249:"\\`u",
// acute accents
193:"\\'A", 225:"\\'a",
201:"\\'E", 233:"\\'e",
205:"\\'I", 237:"\\'i",
211:"\\'O", 243:"\\'o",
218:"\\'U", 250:"\\'u",
// circumflexes
194:"\\^A", 226:"\\^a",
202:"\\^E", 234:"\\^e",
206:"\\^I", 238:"\\^i",
212:"\\^O", 244:"\\^o",
219:"\\^U", 251:"\\^u",
// tildes
195:"\\~A", 227:"\\~a",
213:"\\~O", 245:"\\~o",
209:"\\~N", 241:"\\~n",
// umlauts
196:'\\"A', 228:'\\"a',
203:'\\"E', 235:'\\"e',
207:'\\"I', 239:'\\"i',
214:'\\"O', 246:'\\"o',
220:'\\"U', 252:'\\"u',
// cidillas
191:"\\c{C}", 231:"\\c{c}",
// AE norwegian tings
198:"{\\AE}", 230:"{\\ae}",
// o norwegian things
216:"{\\o}", 248:"{\\O}",
// a norweigan things
197:"{\\AA}", 229:"{\\aa}"
};
function processField(item, field, value) {
if(fieldMap[field]) {
item[fieldMap[field]] = value;
} else if(inputFieldMap[field]) {
item[inputFieldMap[field]] = value;
} else if(field == "journal") {
if(item.publicationTitle) {
// we already had an fjournal
item.journalAbbreviation = value
} else {
item.publicationTitle = value;
}
} else if(field == "fjournal") {
if(item.publicationTitle) {
// move publicationTitle to abbreviation
item.journalAbbreviation = value;
}
item.publicationTitle = value;
} else if(field == "author" || field == "editor") {
// parse authors/editors
var names = value.split(" and ");
for each(var name in names) {
item.creators.push(Zotero.Utilities.cleanAuthor(name, field,
(name.indexOf(",") != -1)));
}
} else if(field == "institution" || field == "organization") {
item.backupPublisher = value;
} else if(field == "number"){ // fix for techreport
if (item.itemType == "report") {
item.reportNumber = value;
} else {
item.issue = value;
}
} else if(field == "month") {
var monthIndex = months.indexOf(value.toLowerCase());
if(monthIndex != -1) {
value = Zotero.Utilities.formatDate({month:monthIndex});
} else {
value += " ";
}
if(item.date) {
if(value.indexOf(item.date) != -1) {
// value contains year and more
item.date = value;
} else {
item.date = value+item.date;
}
} else {
item.date = value;
}
} else if(field == "year") {
if(item.date) {
if(item.date.indexOf(value) == -1) {
// date does not already contain year
item.date += value;
}
} else {
item.date = value;
}
} else if(field == "pages") {
item.pages = value.replace(/--/g, "-");
} else if(field == "note" || field == "annote") {
item.extra += "\n"+value;
} else if(field == "howpublished") {
item.extra += "\nPublished: "+value;
} else if(field == "keywords") {
if(value.indexOf(",") == -1) {
// keywords/tags
item.tags = value.split(" ");
} else {
item.tags = value.split(/, ?/g);
}
}
}
function getFieldValue() {
// read whitespace
var read = Zotero.read(1);
while(" \n\r\t".indexOf(read) != -1) {
read = Zotero.read(1);
}
var value = "";
// now, we have the first character of the field
if("0123456789".indexOf(read) != -1) {
value += read;
// character is a number
while((read = Zotero.read(1)) && ("0123456789".indexOf(read) != -1))
{
value += read;
}
} else if(read == "{") {
// character is a brace
var openBraces = 1;
while(read = Zotero.read(1)) {
if(read == "{" && value[value.length-1] != "\\") {
openBraces++;
value += "{";
} else if(read == "}" && value[value.length-1] != "\\") {
openBraces--;
if(openBraces == 0) {
break;
} else {
value += "}";
}
} else {
value += read;
}
}
} else if(read == '"') {
var openBraces = 0;
while(read = Zotero.read(1)) {
if(read == "{" && value[value.length-1] != "\\") {
openBraces++;
value += "{";
} else if(read == "}" && value[value.length-1] != "\\") {
openBraces--;
value += "}";
} else if(read == '"' && openBraces == 0) {
break;
} else {
value += read;
}
}
}
if(value.length > 1) {
// replace accented characters (yucky slow)
for(var i in accentedCharacters) {
value = value.replace(accentedCharacters[i], i);
}
// kill braces
value = value.replace(/([^\\])[{}]+/g, "$1");
if(value[0] == "{") {
value = value.substr(1);
}
// chop off backslashes
value = value.replace(/([^\\])\\([#$%&~_^\\{}])/g, "$1$2");
value = value.replace(/([^\\])\\([#$%&~_^\\{}])/g, "$1$2");
if(value[0] == "\\" && "#$%&~_^\\{}".indexOf(value[1]) != -1) {
value = value.substr(1);
}
if(value[value.length-1] == "\\" && "#$%&~_^\\
{}".indexOf(value[value.length-2]) != -1) {
value = value.substr(0, value.length-1);
}
value = value.replace(/\\\\/g, "\\");
value = value.replace(/\s+/g, " ");
}
return value;
}
function beginRecord(type, closeChar) {
type = Zotero.Utilities.cleanString(type.toLowerCase());
zoteroType = bibtex2zoteroTypeMap[type];
if (!zoteroType) {
Zotero.debug("discarded item from BibTeX; type was "+type);
}
var item = new Zotero.Item(zoteroType);
item.extra = "";
var field = "";
while(read = Zotero.read(1)) {
if(read == "=") { // equals begin a field
var value = getFieldValue();
if(item) {
processField(item, field.toLowerCase(), value);
}
field = "";
} else if(read == ",") { // commas reset
field = "";
} else if(read == closeChar) {
if(item) {
if(item.extra) item.extra = item.extra.substr(1); // chop \n
item.complete();
}
return;
} else if(" \n\r\t".indexOf(read) == -1) { // skip whitespace
field += read;
}
}
}
function doImport() {
// make regular expressions out of values
var newArray = new Array();
for(var i in accentedCharacters) {
newArray[String.fromCharCode(i)] = new
RegExp(accentedCharacters[i].replace(/\\/g, "\\\\"), "g");
}
accentedCharacters = newArray;
var read = "", text = "", recordCloseElement = false;
var type = false;
while(read = Zotero.read(1)) {
if(read == "@") {
type = "";
} else if(type !== false) {
if(read == "{") { // possible open character
beginRecord(type, "}");
type = false;
} else if(read == "(") { // possible open character
beginRecord(type, ")");
type = false;
} else {
type += read;
}
}
}
}
// some fields are, in fact, macros. If that is the case then we
should not put the
// data in the braces as it will cause the macros to not expand
properly
function writeMacroField(field, value) {
if (!value) {
return;
}
value = value.toString();
// replace naughty chars
value = value.replace(/([#$%&~_^\\{}])/g, "\\$1");
// replace accented characters
for (var i in accentedCharacters) {
value = value.replace(accentedCharacters[i], i);
}
// replace other accented characters
value = value.replace(/[\u0080-\uFFFF]/g, "?")
// write
Zotero.write(",\n\t"+field+" = "+value);
}
function writeField(field, value) {
if(!value) return;
value = value.toString();
// replace naughty chars
value = value.replace(/([#$%&~_^\\{}])/g, "\\$1");
// we assume people who use braces in their title probably did so
intentionally
if (field == "title") {
value = value.replace(/\\([{}])/g, "$1");
}
// replace accented characters
for (var i in accentedCharacters) {
value = value.replace(accentedCharacters[i], i);
}
// replace other accented characters
value = value.replace(/[\u0080-\uFFFF]/g, "?")
// write
Zotero.write(",\n\t"+field+" = {"+value+"}");
}
var numberRe = /^[0-9]+/;
function doExport() {
// switch keys and values of accented characters
var newArray = new Array();
for(var i in accentedCharacters) {
newArray["{"+accentedCharacters[i]+"}"] = new
RegExp(String.fromCharCode(i), "g");
}
accentedCharacters = newArray;
//Zotero.write("% BibTeX export generated by Zotero
"+Zotero.Utilities.getVersion());
var first = true;
var citekeys = new Object();
var item;
while(item = Zotero.nextItem()) {
// determine type
var type = zotero2bibtexTypeMap[item.itemType];
if (typeof(type) == 'function') {
type = type(item);
}
if(!type) type = "misc";
// create a unique citation key
var basekey = "";
if(item.creators && item.creators[0] && item.creators[0].lastName) {
basekey = item.creators[0].lastName.toLowerCase().replace(/ /
g,"_").replace(/,/g,"");
}
// include the item title as part of the citation key
if (item["title"]) {
// this is a list of words that should not appear as part of the
citation key
var bannedTitleKeys = {"a" : 1, "an" : 1, "does": 1, "how": 1,
"it's": 1, "on" : 1, "some": 1, "the" : 1, "this" : 1, "why" : 1 };
var titleElements = item["title"].split(" ");
var appendKey = "";
for (te in titleElements) {
if (!bannedTitleKeys[titleElements[te].toLowerCase()]) {
appendKey = "_" + titleElements[te].toLowerCase() + "_";
break;
}
}
basekey = basekey + appendKey;
}
if(item.date) {
var date = Zotero.Utilities.strToDate(item.date);
if(date.year && numberRe.test(date.year)) {
basekey += date.year;
}
}
// make sure we do not have any other funny characters
basekey = basekey.replace(/[\. ,':\"!&]/g,"");
var citekey = basekey;
var i = 0;
while(citekeys[citekey]) {
i++;
citekey = basekey+"-"+i;
}
citekeys[citekey] = true;
// write citation key
Zotero.write((first ? "" : ",\n\n") + "@"+type+"{"+citekey);
first = false;
for(var field in fieldMap) {
if(item[fieldMap[field]]) {
writeField(field, item[fieldMap[field]]);
}
}
if(item.proceedingsTitle || item.conferenceName) {
writeField("booktitle", item.proceedingsTitle ||
item.conferenceName);
}
if(item.publicationTitle) {
if(item.itemType == "chapter") {
writeField("booktitle", item.publicationTitle);
} else {
writeField("journal", item.publicationTitle);
}
}
if(item.publisher) {
if(item.itemType == "thesis") {
writeField("school", item.publisher);
} else {
writeField("publisher", item.publisher);
}
}
if(item.creators && item.creators.length) {
// split creators into subcategories
var author = "";
var editor = "";
for each(var creator in item.creators) {
var creatorString = creator.lastName;
if (creator.firstName) {
creatorString = creator.firstName + " " + creator.lastName;
}
if (creator.creatorType == "editor") {
editor += " and "+creatorString;
} else {
author += " and "+creatorString;
}
}
if(author) {
writeField("author", author.substr(5));
}
if(editor) {
writeField("editor", editor.substr(5));
}
}
if(item.date) {
// need to use non-localized abbreviation
if(date.month) {
writeMacroField("month", months[date.month]);
}
if(date.year) {
writeField("year", date.year);
}
}
if(item.extra) {
writeField("note", item.extra);
}
if(item.tags && item.tags.length) {
var tagString = "";
for each(var tag in item.tags) {
tagString += ","+tag.tag;
}
writeField("keywords", tagString.substr(1));
}
if(item.pages) {
writeField("pages", item.pages);
}
if(item.itemType == "webpage") {
writeField("howpublished", item.url);
}
Zotero.write("\n}");
}
}