Skip to content

Instantly share code, notes, and snippets.

@liob
Last active April 13, 2021 13:59
Show Gist options
  • Save liob/6009553 to your computer and use it in GitHub Desktop.
Save liob/6009553 to your computer and use it in GitHub Desktop.
Zotero translator - BibTeX key for Markdown based on the work of Peter O'Brien, Simon Kornblith and Richard Karnesky
{
"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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment