Skip to content

Instantly share code, notes, and snippets.

@kongscn
Forked from liob/BibTexCiteKeyForMarkdown.js
Created December 28, 2015 07:40
Show Gist options
  • Save kongscn/fa50e2544977662902b6 to your computer and use it in GitHub Desktop.
Save kongscn/fa50e2544977662902b6 to your computer and use it in GitHub Desktop.

Revisions

  1. @liob liob revised this gist Jul 16, 2013. No changes.
  2. @liob liob created this gist Jul 16, 2013.
    233 changes: 233 additions & 0 deletions BibTexCiteKeyForMarkdown.js
    Original file line number Diff line number Diff line change
    @@ -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;

    }

    }