|
@@ -22,6 +22,24 @@ |
|
|
|
"lastUpdated": "2019-02-03 17:45:00" |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
BibTeX Translator |
|
|
|
Copyright (C) 2019 CHNM, Simon Kornblith, Richard Karnesky and Emiliano heyns |
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify |
|
|
|
it under the terms of the GNU Affero General Public License as published by |
|
|
|
the Free Software Foundation, either version 3 of the License, or |
|
|
|
(at your option) any later version. |
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
GNU Affero General Public License for more details. |
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License |
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
*/ |
|
|
|
|
|
|
|
function detectImport() { |
|
|
|
var maxChars = 1048576; // 1MB |
|
|
|
|
|
@@ -57,7 +75,7 @@ function detectImport() { |
|
|
|
} |
|
|
|
|
|
|
|
block = ""; |
|
|
|
} else if (" \n\r\t".indexOf(chr) == -1) { |
|
|
|
} else if (!" \n\r\t".includes(chr)) { |
|
|
|
block += chr; |
|
|
|
} |
|
|
|
} |
|
@@ -325,7 +343,7 @@ function processField(item, field, value, rawValue) { |
|
|
|
if (!name) continue; |
|
|
|
|
|
|
|
// Names in BibTeX can have three commas |
|
|
|
pieces = splitUnprotected(name, /\s*,\s*/g); |
|
|
|
var pieces = splitUnprotected(name, /\s*,\s*/g); |
|
|
|
var creator = {}; |
|
|
|
if (pieces.length > 1) { |
|
|
|
creator.firstName = pieces.pop(); |
|
@@ -343,7 +361,7 @@ function processField(item, field, value, rawValue) { |
|
|
|
lastName: unescapeBibTeX(name), |
|
|
|
creatorType: field, |
|
|
|
fieldMode: 1 |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
item.creators.push(creator); |
|
|
|
} |
|
@@ -370,7 +388,7 @@ function processField(item, field, value, rawValue) { |
|
|
|
} |
|
|
|
|
|
|
|
if (item.date) { |
|
|
|
if (value.indexOf(item.date) != -1) { |
|
|
|
if (value.includes(item.date)) { |
|
|
|
// value contains year and more |
|
|
|
item.date = value; |
|
|
|
} else { |
|
@@ -381,7 +399,7 @@ function processField(item, field, value, rawValue) { |
|
|
|
} |
|
|
|
} else if (field == "year") { |
|
|
|
if (item.date) { |
|
|
|
if (item.date.indexOf(value) == -1) { |
|
|
|
if (!item.date.includes(value)) { |
|
|
|
// date does not already contain year |
|
|
|
item.date += value; |
|
|
|
} |
|
@@ -642,12 +660,12 @@ function unescapeBibTeX(value) { |
|
|
|
value = mapTeXmarkup(value); |
|
|
|
for (var mapped in reversemappingTable) { // really really slow! |
|
|
|
var unicode = reversemappingTable[mapped]; |
|
|
|
while (value.indexOf(mapped) !== -1) { |
|
|
|
while (value.includes(mapped)) { |
|
|
|
Zotero.debug("Replace " + mapped + " in " + value + " with " + unicode); |
|
|
|
value = value.replace(mapped, unicode); |
|
|
|
} |
|
|
|
mapped = mapped.replace(/[{}]/g, ""); |
|
|
|
while (value.indexOf(mapped) !== -1) { |
|
|
|
while (value.includes(mapped)) { |
|
|
|
//Z.debug(value) |
|
|
|
Zotero.debug("Replace(2) " + mapped + " in " + value + " with " + unicode); |
|
|
|
value = value.replace(mapped, unicode); |
|
@@ -663,17 +681,17 @@ function unescapeBibTeX(value) { |
|
|
|
// chop off backslashes |
|
|
|
value = value.replace(/([^\\])\\([#$%&~_^\\{}])/g, "$1$2"); |
|
|
|
value = value.replace(/([^\\])\\([#$%&~_^\\{}])/g, "$1$2"); |
|
|
|
if (value[0] == "\\" && "#$%&~_^\\{}".indexOf(value[1]) != -1) { |
|
|
|
if (value[0] == "\\" && "#$%&~_^\\{}".includes(value[1])) { |
|
|
|
value = value.substr(1); |
|
|
|
} |
|
|
|
if (value[value.length-1] == "\\" && "#$%&~_^\\{}".indexOf(value[value.length-2]) != -1) { |
|
|
|
if (value[value.length-1] == "\\" && "#$%&~_^\\{}".includes(value[value.length-2])) { |
|
|
|
value = value.substr(0, value.length-1); |
|
|
|
} |
|
|
|
value = value.replace(/\\\\/g, "\\"); |
|
|
|
value = value.replace(/\s+/g, " "); |
|
|
|
|
|
|
|
// Unescape HTML entities coming from web translators |
|
|
|
if (Zotero.parentTranslator && value.indexOf('&') != -1) { |
|
|
|
if (Zotero.parentTranslator && value.includes('&')) { |
|
|
|
value = value.replace(/&#?\w+;/g, function(entity) { |
|
|
|
var char = ZU.unescapeHTML(entity); |
|
|
|
if (char == entity) char = ZU.unescapeHTML(entity.toLowerCase()); // Sometimes case can be incorrect and entities are case-sensitive |
|
@@ -733,12 +751,12 @@ function processComment() { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (comment.indexOf('jabref-meta: groupstree:') == 0) { |
|
|
|
if (comment.startsWith('jabref-meta: groupstree:')) { |
|
|
|
if (jabref.format != 3) { |
|
|
|
Zotero.debug("jabref: fatal: unsupported group format: " + jabref.format); |
|
|
|
return; |
|
|
|
} |
|
|
|
comment = comment.replace(/^jabref-meta: groupstree:/, '').replace(/[\r\n]/gm, '') |
|
|
|
comment = comment.replace(/^jabref-meta: groupstree:/, '').replace(/[\r\n]/gm, ''); |
|
|
|
|
|
|
|
var records = jabrefSplit(comment, ';'); |
|
|
|
while (records.length > 0) { |
|
@@ -753,8 +771,8 @@ function processComment() { |
|
|
|
return; |
|
|
|
} |
|
|
|
record.level = parseInt(record.data[1]); |
|
|
|
record.type = record.data[2] |
|
|
|
record.name = record.data[3] |
|
|
|
record.type = record.data[2]; |
|
|
|
record.name = record.data[3]; |
|
|
|
record.intersection = keys.shift(); // 0 = independent, 1 = intersection, 2 = union |
|
|
|
|
|
|
|
if (isNaN(record.level)) { |
|
@@ -788,9 +806,9 @@ function processComment() { |
|
|
|
var path = collectionPath[i]; |
|
|
|
Zotero.debug("jabref: looking for child " + path + " under " + collection.name); |
|
|
|
|
|
|
|
var child = jabrefCollect(collection.children, function(n) { return (n.name == path)}) |
|
|
|
var child = jabrefCollect(collection.children, function(n) { return (n.name == path); }); |
|
|
|
if (child.length != 0) { |
|
|
|
child = child[0] |
|
|
|
child = child[0]; |
|
|
|
Zotero.debug("jabref: child " + child.name + " found under " + collection.name); |
|
|
|
} else { |
|
|
|
child = new Zotero.Collection(); |
|
@@ -807,23 +825,23 @@ function processComment() { |
|
|
|
} |
|
|
|
|
|
|
|
if (parentCollection) { |
|
|
|
parentCollection = jabrefCollect(parentCollection.children, function(n) { return (n.type == 'item') }); |
|
|
|
parentCollection = jabrefCollect(parentCollection.children, function(n) { return (n.type == 'item'); }); |
|
|
|
} |
|
|
|
|
|
|
|
if (record.intersection == '2' && parentCollection) { // union with parent |
|
|
|
collection.children = parentCollection; |
|
|
|
} |
|
|
|
|
|
|
|
while (keys.length > 0) { |
|
|
|
key = keys.shift(); |
|
|
|
var key = keys.shift(); |
|
|
|
if (key != '') { |
|
|
|
Zotero.debug('jabref: adding ' + key + ' to ' + collection.name); |
|
|
|
collection.children.push({type: 'item', id: key}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (parentCollection && record.intersection == '1') { // intersection with parent |
|
|
|
collection.children = jabrefMap(collection.children, function(n) { parentCollection.indexOf(n) !== -1; }); |
|
|
|
collection.children = jabrefMap(collection.children, function(n) { parentCollection.includes(n); }); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
@@ -858,7 +876,7 @@ function beginRecord(type, closeChar) { |
|
|
|
if (read == "=") { // equals begin a field |
|
|
|
// read whitespace |
|
|
|
var read = Zotero.read(1); |
|
|
|
while (" \n\r\t".indexOf(read) != -1) { |
|
|
|
while (" \n\r\t".includes(read)) { |
|
|
|
read = Zotero.read(1); |
|
|
|
} |
|
|
|
|
|
@@ -917,7 +935,7 @@ function beginRecord(type, closeChar) { |
|
|
|
return item.complete(); |
|
|
|
} |
|
|
|
return; |
|
|
|
} else if (" \n\r\t".indexOf(read) == -1) { // skip whitespace |
|
|
|
} else if (" \n\r\t".includes(read)) { // skip whitespace |
|
|
|
field += read; |
|
|
|
} |
|
|
|
} |
|
@@ -1000,7 +1018,7 @@ function writeField(field, value, isMacro) { |
|
|
|
// I hope these are all the escape characters! |
|
|
|
value = escapeSpecialCharacters(value); |
|
|
|
|
|
|
|
if (caseProtectedFields.indexOf(field) != -1) { |
|
|
|
if (caseProtectedFields.includes(field)) { |
|
|
|
value = ZU.XRegExp.replace(value, protectCapsRE, "$1{$2$3}"); // only $2 or $3 will have a value, not both |
|
|
|
} |
|
|
|
} |
|
@@ -1061,7 +1079,7 @@ function isTitleCase(string) { |
|
|
|
while (word = wordRE.exec(string)) { |
|
|
|
word = word[1]; |
|
|
|
if (word.search(/\d/) != -1 //ignore words with numbers (including just numbers) |
|
|
|
|| skipWords.indexOf(word.toLowerCase()) != -1) { |
|
|
|
|| skipWords.includes(word.toLowerCase())) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
@@ -1074,13 +1092,13 @@ function isTitleCase(string) { |
|
|
|
// See http://tex.stackexchange.com/questions/230750/open-brace-in-bibtex-fields/230754 |
|
|
|
var vphantomRe = /\\vphantom{\\}}((?:.(?!\\vphantom{\\}}))*)\\vphantom{\\{}/g; |
|
|
|
function escapeSpecialCharacters(str) { |
|
|
|
var newStr = str.replace(/[|\<\>\~\^\\\{\}]/g, function(c) { return alwaysMap[c] }) |
|
|
|
var newStr = str.replace(/[|\<\>\~\^\\\{\}]/g, function(c) { return alwaysMap[c]; }) |
|
|
|
.replace(/([\#\$\%\&\_])/g, "\\$1"); |
|
|
|
|
|
|
|
// We escape each brace in the text by making sure that it has a counterpart, |
|
|
|
// but sometimes this is overkill if the brace already has a counterpart in |
|
|
|
// the text. |
|
|
|
if (newStr.indexOf('\\vphantom') != -1) { |
|
|
|
if (newStr.includes('\\vphantom')) { |
|
|
|
var m; |
|
|
|
while (m = vphantomRe.exec(newStr)) { |
|
|
|
// Can't use a simple replace, because we want to match up inner with inner |
|
@@ -1178,7 +1196,7 @@ var citeKeyConversions = { |
|
|
|
} |
|
|
|
return "nodate"; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function buildCiteKey (item, extraFields, citekeys) { |
|
@@ -1191,7 +1209,7 @@ function buildCiteKey (item, extraFields, citekeys) { |
|
|
|
|
|
|
|
var basekey = ""; |
|
|
|
var counter = 0; |
|
|
|
citeKeyFormatRemaining = citeKeyFormat; |
|
|
|
var citeKeyFormatRemaining = citeKeyFormat; |
|
|
|
while (citeKeyConversionsRe.test(citeKeyFormatRemaining)) { |
|
|
|
if (counter > 100) { |
|
|
|
Zotero.debug("Pathological BibTeX format: " + citeKeyFormat); |
|
@@ -1478,7 +1496,7 @@ var exports = { |
|
|
|
"doImport": doImport, |
|
|
|
"setKeywordDelimRe": setKeywordDelimRe, |
|
|
|
"setKeywordSplitOnSpace": setKeywordSplitOnSpace |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/* |
|
|
|
* new mapping table based on that from Matthias Steffens, |
|
@@ -2156,12 +2174,12 @@ var mappingTable = { |
|
|
|
"\uFB04":"ffl", // LATIN SMALL LIGATURE FFL |
|
|
|
"\uFB05":"st", // LATIN SMALL LIGATURE LONG S T |
|
|
|
"\uFB06":"st", // LATIN SMALL LIGATURE ST |
|
|
|
/* Derived accented characters */ |
|
|
|
/* Derived accented characters */ |
|
|
|
|
|
|
|
/* These two require the "semtrans" package to work; uncomment to enable */ |
|
|
|
/* "\u02BF":"\{\\Ayn}", // MGR Ayn |
|
|
|
"\u02BE":"\{\\Alif}", // MGR Alif/Hamza |
|
|
|
*/ |
|
|
|
/* These two require the "semtrans" package to work; uncomment to enable */ |
|
|
|
/* "\u02BF":"\{\\Ayn}", // MGR Ayn |
|
|
|
"\u02BE":"\{\\Alif}", // MGR Alif/Hamza |
|
|
|
*/ |
|
|
|
"\u00C0":"{\\`A}", // LATIN CAPITAL LETTER A WITH GRAVE |
|
|
|
"\u00C1":"{\\'A}", // LATIN CAPITAL LETTER A WITH ACUTE |
|
|
|
"\u00C2":"{\\^A}", // LATIN CAPITAL LETTER A WITH CIRCUMFLEX |
|
@@ -2511,7 +2529,7 @@ var reversemappingTable = { |
|
|
|
"{\\OE}" : "\u0152", // LATIN CAPITAL LIGATURE OE |
|
|
|
"{\\oe}" : "\u0153", // LATIN SMALL LIGATURE OE |
|
|
|
"{\\textasciicircum}" : "\u02C6", // MODIFIER LETTER CIRCUMFLEX ACCENT |
|
|
|
// "\\~{}" : "\u02DC", // SMALL TILDE |
|
|
|
// "\\~{}" : "\u02DC", // SMALL TILDE |
|
|
|
"{\\textacutedbl}" : "\u02DD", // DOUBLE ACUTE ACCENT |
|
|
|
|
|
|
|
//Greek Letters Courtesy of Spartanroc |
|
@@ -2568,7 +2586,7 @@ var reversemappingTable = { |
|
|
|
"{\\textquotedblleft}" : "\u201C", // LEFT DOUBLE QUOTATION MARK |
|
|
|
"{\\textquotedblright}" : "\u201D", // RIGHT DOUBLE QUOTATION MARK |
|
|
|
"{\\quotedblbase}" : "\u201E", // DOUBLE LOW-9 QUOTATION MARK |
|
|
|
// "{\\quotedblbase}" : "\u201F", // DOUBLE HIGH-REVERSED-9 QUOTATION MARK |
|
|
|
// "{\\quotedblbase}" : "\u201F", // DOUBLE HIGH-REVERSED-9 QUOTATION MARK |
|
|
|
"{\\textdagger}" : "\u2020", // DAGGER |
|
|
|
"{\\textdaggerdbl}" : "\u2021", // DOUBLE DAGGER |
|
|
|
"{\\textbullet}" : "\u2022", // BULLET |
|
@@ -3707,5 +3725,5 @@ var testCases = [ |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
] |
|
|
|
]; |
|
|
|
/** END TEST CASES **/ |
0 comments on commit
58b257f