|
|
@@ -0,0 +1,233 @@ |
|
|
{ |
|
|
"translatorID": "7cb70025-a888-4a29-a210-93ec52da40d5", |
|
|
"translatorType": 3, |
|
|
"label": "BibTeX key for Markdown", |
|
|
"creator": "created by liob based on the works of Peter O'Brien, Simon Kornblith and Richard Karnesky", |
|
|
"target": "bib", |
|
|
"minVersion": "2.1.9", |
|
|
"maxVersion": null, |
|
|
"priority": 200, |
|
|
"inRepository": true, |
|
|
"browserSupport": "gcsv", |
|
|
"displayOptions": { |
|
|
"exportCharset": "UTF-8", |
|
|
"exportNotes": false, |
|
|
"exportFileData": false |
|
|
}, |
|
|
"lastUpdated": "2013-07-16 17:00:00" |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//%a = first author surname |
|
|
//%y = year |
|
|
//%t = first word of title |
|
|
var citeKeyFormat = "%a_%t_%y"; |
|
|
|
|
|
|
|
|
|
|
|
var zotero2bibtexTypeMap = { |
|
|
"book":"book", |
|
|
"bookSection":"incollection", |
|
|
"journalArticle":"article", |
|
|
"magazineArticle":"article", |
|
|
"newspaperArticle":"article", |
|
|
"thesis":"phdthesis", |
|
|
"letter":"misc", |
|
|
"manuscript":"unpublished", |
|
|
"interview":"misc", |
|
|
"film":"misc", |
|
|
"artwork":"misc", |
|
|
"webpage":"misc", |
|
|
"conferencePaper":"inproceedings", |
|
|
"report":"techreport" |
|
|
}; |
|
|
|
|
|
|
|
|
/* |
|
|
* 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"]; |
|
|
|
|
|
/* |
|
|
* new mapping table based on that from Matthias Steffens, |
|
|
* then enhanced with some fields generated from the unicode table. |
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
var alwaysMap = { |
|
|
"|":"{\\textbar}", |
|
|
"<":"{\\textless}", |
|
|
">":"{\\textgreater}", |
|
|
"~":"{\\textasciitilde}", |
|
|
"^":"{\\textasciicircum}", |
|
|
"\\":"{\\textbackslash}" |
|
|
}; |
|
|
|
|
|
var strings = {}; |
|
|
var keyRe = /[a-zA-Z0-9\-]/; |
|
|
var keywordSplitOnSpace = true; |
|
|
var keywordDelimRe = ',\\s*'; |
|
|
var keywordDelimReFlags = ''; |
|
|
|
|
|
function setKeywordSplitOnSpace( val ) { |
|
|
keywordSplitOnSpace = val; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function mapEscape(character) { |
|
|
return alwaysMap[character]; |
|
|
} |
|
|
|
|
|
function mapAccent(character) { |
|
|
return (mappingTable[character] ? mappingTable[character] : "?"); |
|
|
} |
|
|
|
|
|
// a little substitution function for BibTeX keys, where we don't want LaTeX |
|
|
// escaping, but we do want to preserve the base characters |
|
|
|
|
|
function tidyAccents(s) { |
|
|
var r=s.toLowerCase(); |
|
|
|
|
|
// XXX Remove conditional when we drop Zotero 2.1.x support |
|
|
// This is supported in Zotero 3.0 and higher |
|
|
if (ZU.removeDiacritics !== undefined) |
|
|
r = ZU.removeDiacritics(r, true); |
|
|
else { |
|
|
// We fall back on the replacement list we used previously |
|
|
r = r.replace(new RegExp("[ä]", 'g'),"ae"); |
|
|
r = r.replace(new RegExp("[ö]", 'g'),"oe"); |
|
|
r = r.replace(new RegExp("[ü]", 'g'),"ue"); |
|
|
r = r.replace(new RegExp("[àáâãå]", 'g'),"a"); |
|
|
r = r.replace(new RegExp("æ", 'g'),"ae"); |
|
|
r = r.replace(new RegExp("ç", 'g'),"c"); |
|
|
r = r.replace(new RegExp("[èéêë]", 'g'),"e"); |
|
|
r = r.replace(new RegExp("[ìíîï]", 'g'),"i"); |
|
|
r = r.replace(new RegExp("ñ", 'g'),"n"); |
|
|
r = r.replace(new RegExp("[òóôõ]", 'g'),"o"); |
|
|
r = r.replace(new RegExp("œ", 'g'),"oe"); |
|
|
r = r.replace(new RegExp("[ùúû]", 'g'),"u"); |
|
|
r = r.replace(new RegExp("[ýÿ]", 'g'),"y"); |
|
|
} |
|
|
|
|
|
return r; |
|
|
}; |
|
|
|
|
|
var numberRe = /^[0-9]+/; |
|
|
// Below is a list of words that should not appear as part of the citation key |
|
|
// in includes the indefinite articles of English, German, French and Spanish, as well as a small set of English prepositions whose |
|
|
// force is more grammatical than lexical, i.e. which are likely to strike many as 'insignificant'. |
|
|
// The assumption is that most who want a title word in their key would prefer the first word of significance. |
|
|
var citeKeyTitleBannedRe = /\b(a|an|the|some|from|on|in|to|of|do|with|der|die|das|ein|eine|einer|eines|einem|einen|un|une|la|le|l\'|el|las|los|al|uno|una|unos|unas|de|des|del|d\')(\s+|\b)/g; |
|
|
var citeKeyConversionsRe = /%([a-zA-Z])/; |
|
|
var citeKeyCleanRe = /[^a-z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]+/g; |
|
|
|
|
|
var citeKeyConversions = { |
|
|
"a":function (flags, item) { |
|
|
if(item.creators && item.creators[0] && item.creators[0].lastName) { |
|
|
return item.creators[0].lastName.toLowerCase().replace(/ /g,"_").replace(/,/g,""); |
|
|
} |
|
|
return ""; |
|
|
}, |
|
|
"t":function (flags, item) { |
|
|
if (item["title"]) { |
|
|
return item["title"].toLowerCase().replace(citeKeyTitleBannedRe, "").split(/\s+/g)[0]; |
|
|
} |
|
|
return ""; |
|
|
}, |
|
|
"y":function (flags, item) { |
|
|
if(item.date) { |
|
|
var date = Zotero.Utilities.strToDate(item.date); |
|
|
if(date.year && numberRe.test(date.year)) { |
|
|
return date.year; |
|
|
} |
|
|
} |
|
|
return "????"; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function buildCiteKey (item,citekeys) { |
|
|
var basekey = ""; |
|
|
var counter = 0; |
|
|
citeKeyFormatRemaining = citeKeyFormat; |
|
|
while (citeKeyConversionsRe.test(citeKeyFormatRemaining)) { |
|
|
if (counter > 100) { |
|
|
Zotero.debug("Pathological BibTeX format: " + citeKeyFormat); |
|
|
break; |
|
|
} |
|
|
var m = citeKeyFormatRemaining.match(citeKeyConversionsRe); |
|
|
if (m.index > 0) { |
|
|
//add data before the conversion match to basekey |
|
|
basekey = basekey + citeKeyFormatRemaining.substr(0, m.index); |
|
|
} |
|
|
var flags = ""; // for now |
|
|
var f = citeKeyConversions[m[1]]; |
|
|
if (typeof(f) == "function") { |
|
|
var value = f(flags, item); |
|
|
Zotero.debug("Got value " + value + " for %" + m[1]); |
|
|
//add conversion to basekey |
|
|
basekey = basekey + value; |
|
|
} |
|
|
citeKeyFormatRemaining = citeKeyFormatRemaining.substr(m.index + m.length); |
|
|
counter++; |
|
|
} |
|
|
if (citeKeyFormatRemaining.length > 0) { |
|
|
basekey = basekey + citeKeyFormatRemaining; |
|
|
} |
|
|
|
|
|
// for now, remove any characters not explicitly known to be allowed; |
|
|
// we might want to allow UTF-8 citation keys in the future, depending |
|
|
// on implementation support. |
|
|
// |
|
|
// no matter what, we want to make sure we exclude |
|
|
// " # % ' ( ) , = { } ~ and backslash |
|
|
// however, we want to keep the base characters |
|
|
|
|
|
basekey = tidyAccents(basekey); |
|
|
basekey = basekey.replace(citeKeyCleanRe, ""); |
|
|
var citekey = basekey; |
|
|
var i = 0; |
|
|
while(citekeys[citekey]) { |
|
|
i++; |
|
|
citekey = basekey + "-" + i; |
|
|
} |
|
|
citekeys[citekey] = true; |
|
|
return citekey; |
|
|
} |
|
|
|
|
|
function doExport() { |
|
|
//Zotero.write("% BibTeX export generated by Zotero "+Zotero.Utilities.getVersion()); |
|
|
// to make sure the BOM gets ignored |
|
|
|
|
|
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 citekey = buildCiteKey(item, citekeys); |
|
|
|
|
|
// write citation key |
|
|
Zotero.write((first ? "" : "; ") + "@" + citekey); |
|
|
first = false; |
|
|
|
|
|
} |
|
|
|
|
|
} |