SHOW:
|
|
- or go back to the newest paste.
| 1 | {
| |
| 2 | "translatorID": "7cb70025-a888-4a29-a210-93ec52da40d4", | |
| 3 | "translatorType": 3, | |
| 4 | "label": "BibTeX-citep", | |
| 5 | "creator": "Peter O'Brien - from Simon Kornblith and Richard Karnesky", | |
| 6 | "target": "bib", | |
| 7 | "minVersion": "2.1.9", | |
| 8 | "maxVersion": null, | |
| 9 | "priority": 200, | |
| 10 | "inRepository": true, | |
| 11 | "browserSupport": "gcsv", | |
| 12 | "displayOptions": {
| |
| 13 | "exportCharset": "UTF-8", | |
| 14 | "exportNotes": false, | |
| 15 | "exportFileData": false | |
| 16 | }, | |
| 17 | "lastUpdated": "2012-05-31 00:43:00" | |
| 18 | } | |
| 19 | ||
| 20 | ||
| 21 | ||
| 22 | //%a = first author surname | |
| 23 | //%y = year | |
| 24 | //%t = first word of title | |
| 25 | var citeKeyFormat = "%a_%t_%y"; | |
| 26 | ||
| 27 | ||
| 28 | ||
| 29 | var zotero2bibtexTypeMap = {
| |
| 30 | "book":"book", | |
| 31 | "bookSection":"incollection", | |
| 32 | "journalArticle":"article", | |
| 33 | "magazineArticle":"article", | |
| 34 | "newspaperArticle":"article", | |
| 35 | "thesis":"phdthesis", | |
| 36 | "letter":"misc", | |
| 37 | "manuscript":"unpublished", | |
| 38 | "interview":"misc", | |
| 39 | "film":"misc", | |
| 40 | "artwork":"misc", | |
| 41 | "webpage":"misc", | |
| 42 | "conferencePaper":"inproceedings", | |
| 43 | "report":"techreport" | |
| 44 | }; | |
| 45 | ||
| 46 | ||
| 47 | /* | |
| 48 | * three-letter month abbreviations. i assume these are the same ones that the | |
| 49 | * docs say are defined in some appendix of the LaTeX book. (i don't have the | |
| 50 | * LaTeX book.) | |
| 51 | */ | |
| 52 | var months = ["jan", "feb", "mar", "apr", "may", "jun", | |
| 53 | "jul", "aug", "sep", "oct", "nov", "dec"]; | |
| 54 | ||
| 55 | /* | |
| 56 | * new mapping table based on that from Matthias Steffens, | |
| 57 | * then enhanced with some fields generated from the unicode table. | |
| 58 | */ | |
| 59 | ||
| 60 | ||
| 61 | ||
| 62 | var alwaysMap = {
| |
| 63 | "|":"{\\textbar}",
| |
| 64 | "<":"{\\textless}",
| |
| 65 | ">":"{\\textgreater}",
| |
| 66 | "~":"{\\textasciitilde}",
| |
| 67 | "^":"{\\textasciicircum}",
| |
| 68 | "\\":"{\\textbackslash}"
| |
| 69 | }; | |
| 70 | ||
| 71 | var strings = {};
| |
| 72 | var keyRe = /[a-zA-Z0-9\-]/; | |
| 73 | var keywordSplitOnSpace = true; | |
| 74 | var keywordDelimRe = ',\\s*'; | |
| 75 | var keywordDelimReFlags = ''; | |
| 76 | ||
| 77 | function setKeywordSplitOnSpace( val ) {
| |
| 78 | keywordSplitOnSpace = val; | |
| 79 | } | |
| 80 | ||
| 81 | ||
| 82 | ||
| 83 | ||
| 84 | ||
| 85 | ||
| 86 | ||
| 87 | ||
| 88 | ||
| 89 | ||
| 90 | function mapEscape(character) {
| |
| 91 | return alwaysMap[character]; | |
| 92 | } | |
| 93 | ||
| 94 | function mapAccent(character) {
| |
| 95 | return (mappingTable[character] ? mappingTable[character] : "?"); | |
| 96 | } | |
| 97 | ||
| 98 | // a little substitution function for BibTeX keys, where we don't want LaTeX | |
| 99 | // escaping, but we do want to preserve the base characters | |
| 100 | ||
| 101 | function tidyAccents(s) {
| |
| 102 | var r=s.toLowerCase(); | |
| 103 | ||
| 104 | // XXX Remove conditional when we drop Zotero 2.1.x support | |
| 105 | // This is supported in Zotero 3.0 and higher | |
| 106 | - | if (ZU.removeDiacritics == undefined) |
| 106 | + | if (ZU.removeDiacritics !== undefined) |
| 107 | r = ZU.removeDiacritics(r, true); | |
| 108 | else {
| |
| 109 | // We fall back on the replacement list we used previously | |
| 110 | r = r.replace(new RegExp("[ä]", 'g'),"ae");
| |
| 111 | r = r.replace(new RegExp("[ö]", 'g'),"oe");
| |
| 112 | r = r.replace(new RegExp("[ü]", 'g'),"ue");
| |
| 113 | r = r.replace(new RegExp("[àáâãå]", 'g'),"a");
| |
| 114 | r = r.replace(new RegExp("æ", 'g'),"ae");
| |
| 115 | r = r.replace(new RegExp("ç", 'g'),"c");
| |
| 116 | r = r.replace(new RegExp("[èéêë]", 'g'),"e");
| |
| 117 | r = r.replace(new RegExp("[ìíîï]", 'g'),"i");
| |
| 118 | r = r.replace(new RegExp("ñ", 'g'),"n");
| |
| 119 | r = r.replace(new RegExp("[òóôõ]", 'g'),"o");
| |
| 120 | r = r.replace(new RegExp("œ", 'g'),"oe");
| |
| 121 | r = r.replace(new RegExp("[ùúû]", 'g'),"u");
| |
| 122 | r = r.replace(new RegExp("[ýÿ]", 'g'),"y");
| |
| 123 | } | |
| 124 | ||
| 125 | return r; | |
| 126 | }; | |
| 127 | ||
| 128 | var numberRe = /^[0-9]+/; | |
| 129 | // Below is a list of words that should not appear as part of the citation key | |
| 130 | // in includes the indefinite articles of English, German, French and Spanish, as well as a small set of English prepositions whose | |
| 131 | // force is more grammatical than lexical, i.e. which are likely to strike many as 'insignificant'. | |
| 132 | // The assumption is that most who want a title word in their key would prefer the first word of significance. | |
| 133 | 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; | |
| 134 | var citeKeyConversionsRe = /%([a-zA-Z])/; | |
| 135 | var citeKeyCleanRe = /[^a-z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]+/g; | |
| 136 | ||
| 137 | var citeKeyConversions = {
| |
| 138 | "a":function (flags, item) {
| |
| 139 | if(item.creators && item.creators[0] && item.creators[0].lastName) {
| |
| 140 | return item.creators[0].lastName.toLowerCase().replace(/ /g,"_").replace(/,/g,""); | |
| 141 | } | |
| 142 | return ""; | |
| 143 | }, | |
| 144 | "t":function (flags, item) {
| |
| 145 | if (item["title"]) {
| |
| 146 | return item["title"].toLowerCase().replace(citeKeyTitleBannedRe, "").split(/\s+/g)[0]; | |
| 147 | } | |
| 148 | return ""; | |
| 149 | }, | |
| 150 | "y":function (flags, item) {
| |
| 151 | if(item.date) {
| |
| 152 | var date = Zotero.Utilities.strToDate(item.date); | |
| 153 | if(date.year && numberRe.test(date.year)) {
| |
| 154 | return date.year; | |
| 155 | } | |
| 156 | } | |
| 157 | return "????"; | |
| 158 | } | |
| 159 | } | |
| 160 | ||
| 161 | ||
| 162 | function buildCiteKey (item,citekeys) {
| |
| 163 | var basekey = ""; | |
| 164 | var counter = 0; | |
| 165 | citeKeyFormatRemaining = citeKeyFormat; | |
| 166 | while (citeKeyConversionsRe.test(citeKeyFormatRemaining)) {
| |
| 167 | if (counter > 100) {
| |
| 168 | Zotero.debug("Pathological BibTeX format: " + citeKeyFormat);
| |
| 169 | break; | |
| 170 | } | |
| 171 | var m = citeKeyFormatRemaining.match(citeKeyConversionsRe); | |
| 172 | if (m.index > 0) {
| |
| 173 | //add data before the conversion match to basekey | |
| 174 | basekey = basekey + citeKeyFormatRemaining.substr(0, m.index); | |
| 175 | } | |
| 176 | var flags = ""; // for now | |
| 177 | var f = citeKeyConversions[m[1]]; | |
| 178 | if (typeof(f) == "function") {
| |
| 179 | var value = f(flags, item); | |
| 180 | Zotero.debug("Got value " + value + " for %" + m[1]);
| |
| 181 | //add conversion to basekey | |
| 182 | basekey = basekey + value; | |
| 183 | } | |
| 184 | citeKeyFormatRemaining = citeKeyFormatRemaining.substr(m.index + m.length); | |
| 185 | counter++; | |
| 186 | } | |
| 187 | if (citeKeyFormatRemaining.length > 0) {
| |
| 188 | basekey = basekey + citeKeyFormatRemaining; | |
| 189 | } | |
| 190 | ||
| 191 | // for now, remove any characters not explicitly known to be allowed; | |
| 192 | // we might want to allow UTF-8 citation keys in the future, depending | |
| 193 | // on implementation support. | |
| 194 | // | |
| 195 | // no matter what, we want to make sure we exclude | |
| 196 | // " # % ' ( ) , = { } ~ and backslash
| |
| 197 | // however, we want to keep the base characters | |
| 198 | ||
| 199 | basekey = tidyAccents(basekey); | |
| 200 | basekey = basekey.replace(citeKeyCleanRe, ""); | |
| 201 | var citekey = basekey; | |
| 202 | var i = 0; | |
| 203 | while(citekeys[citekey]) {
| |
| 204 | i++; | |
| 205 | citekey = basekey + "-" + i; | |
| 206 | } | |
| 207 | citekeys[citekey] = true; | |
| 208 | return citekey; | |
| 209 | } | |
| 210 | ||
| 211 | function doExport() {
| |
| 212 | //Zotero.write("% BibTeX export generated by Zotero "+Zotero.Utilities.getVersion());
| |
| 213 | // to make sure the BOM gets ignored | |
| 214 | ||
| 215 | var first = true; | |
| 216 | var citekeys = new Object(); | |
| 217 | var item; | |
| 218 | while(item = Zotero.nextItem()) {
| |
| 219 | // determine type | |
| 220 | var type = zotero2bibtexTypeMap[item.itemType]; | |
| 221 | if (typeof(type) == "function") { type = type(item); }
| |
| 222 | if(!type) type = "misc"; | |
| 223 | ||
| 224 | // create a unique citation key | |
| 225 | var citekey = buildCiteKey(item, citekeys); | |
| 226 | ||
| 227 | // write citation key | |
| 228 | Zotero.write((first ? "\\citep{" : ",") + citekey);
| |
| 229 | first = false; | |
| 230 | ||
| 231 | } | |
| 232 | ||
| 233 | Zotero.write("}");
| |
| 234 | } |