-
Notifications
You must be signed in to change notification settings - Fork 0
/
BibTexCiteKeyForMarkdown.js
executable file
·233 lines (192 loc) · 6.35 KB
/
BibTexCiteKeyForMarkdown.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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;
}
}