Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion SAMPLE.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ var bibtexParse = require('bibtex-parse-js');

var sample = bibtexParse.toJSON('@article{sample1,title={sample title}}');

# Will conolse log:
/*
# Will console log:
#
# [ { citationKey: 'SAMPLE1',
# entryType: 'ARTICLE',
# entryTags: { TITLE: 'sample title' } } ]
#
*/
console.log(sample);
103 changes: 96 additions & 7 deletions bibtexParse.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,12 @@
return this.value_quotes();
} else {
var k = this.key();
if (k.match("^[0-9]+$"))
return k;
if (k.match("^[0-9]+\n*$"))
return parseInt(k);
else if (this.months.indexOf(k.toLowerCase()) >= 0)
return k.toLowerCase();
else
throw "Value expected: single_value" + this.input.substring(start) + ' for key: ' + k;
throw "Value expected: single_value " + this.input.substring(start) + ' for key: ' + k;

};
};
Expand All @@ -190,7 +190,11 @@
this.match("#");
values.push(this.single_value());
};
return values.join("");
if(values.length == 1) {
return values[0];
} else {
return values.join("");
}
};

this.key = function(optional) {
Expand Down Expand Up @@ -238,8 +242,16 @@
break;
}
;
kv = this.key_equals_value();
this.currentEntry['entryTags'][kv[0]] = kv[1];
try {
kv = this.key_equals_value();
this.currentEntry['entryTags'][kv[0]] = kv[1];
} catch (e) {
if(("" + e).includes("Value expected, equals sign missing: key_equals_value")) {
console.warn("Warning: ignoring line");
} else {
throw new Error(e);
}
}
};
};

Expand Down Expand Up @@ -302,7 +314,15 @@
} else {
this.entry(d);
}
this.match("}");
try {
this.match("}");
} catch (e) {
if(("" + e).includes("Token mismatch: match")) {
console.warn(e + ", ignoring line");
} else {
throw new Error(e);
}
}
};

this.alernativeCitationKey();
Expand All @@ -311,6 +331,75 @@

exports.toJSON = function(bibtex) {
var b = new BibtexParser();
function cleanBibtex(bibtex_code) {
// searches for lines that should begin with @, but dont, and add @ for resiliency
var at_regex = /(\s+|^)(\w+\{)/ig;
bibtex_code = bibtex_code.replace(at_regex, (match) => `${match[1].replace(/[\n\r\R]*/, "")}\n@${match.replace(/[\n\r\R]*/, "")}`);

// remove spaces before @ at beginning of line
var space_regex = /^\s*@/g;
bibtex_code = bibtex_code.replace(space_regex, "@");

var search_missing_commas_regex_stage_one = /(.*=.*)/g;
bibtex_code = bibtex_code.replace(search_missing_commas_regex_stage_one, "$1,");

var search_missing_commas_regex_stage_two = /(,\s*)+\s*$/g;
bibtex_code = bibtex_code.replace(search_missing_commas_regex_stage_two, ",\n");

var find_unfinished_double_quotes = /(=\s*"[^"]*?),+/g;
bibtex_code = bibtex_code.replace(find_unfinished_double_quotes, `$1",`);

var find_unfinished_bracket_quotes = /(=\s*\{[^\}]*?),+/g;
bibtex_code = bibtex_code.replace(find_unfinished_bracket_quotes, `$1},`);

var find_missing_quotation = /(.*=)([^\{"'].*?[^\}"']),/g;
bibtex_code = bibtex_code.replace(find_missing_quotation, `$1{$2},`);

var find_missing_bracket_quote_start = /(.*=)([^\{].*?\}),/g;
bibtex_code = bibtex_code.replace(find_missing_bracket_quote_start, `$1{$2,`);

var find_missing_article_type = /^\s*(?<=@)([a-zA-Z0-9_]*)/g;
if(bibtex_code.match(find_missing_article_type)) {
bibtex_code = bibtex_code.replace(find_missing_article_type, `@article{$1`);
console.log("Found no article type, added @article");
}

var remove_double_commas = /,,+/g
bibtex_code = bibtex_code.replace(remove_double_commas, ",\n");

console.log(bibtex_code);

var lines = bibtex_code.split(/[\n\r]/);

function line_could_be_valid_syntax (line) {
if(line.match("^\s*@")) {
return true;
} else if(line.match("=")) {
return true;
} else if(line.match("}")) {
return true;
} else if(line.match(/^\s*$/)) {
return true;
} else {
return false;
}
}

var new_lines = [];

for (var i = 0; i < lines.length; i++) {
if(line_could_be_valid_syntax(lines[i])) {
new_lines.push(lines[i]);
} else {
console.warn("The line " + lines[i] + " does not seem to contain a valid bibtex line");
}
}

return new_lines.join("\n");
}

bibtex = cleanBibtex(bibtex);

b.setInput(bibtex);
b.bibtex();
return b.entries;
Expand Down
166 changes: 166 additions & 0 deletions example_site/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html>
<head>
<title>BibTeX Parser</title>
</head>
<body>
<script src="../bibtexParse.js"></script>

<h1>BibTeX to JSON Parser</h1>

<label for="bibtexInput">Enter BibTeX Code:</label>
<textarea id="bibtexInput" rows="5" cols="50">
@article{sample1,
title={sample title},
author="sample title"
}

@online{sample2,
title={sample title 2},
author="sample title 2",
year=1995,
url="https://google.de"
}

online{sample2,
title={sample title 2},
author="sample title 2"
year=1995,
url="https://google.de"
}


online{sample3,
title={sample title 3,
author="sample title 3"
year=19909,
url="https://google.de
}

online{sample4,
title=sample title 4,
author=sample title 4
year=199,
url="https://google.de
}

online{sample5,
title=sample title 5},
author=sample title 5}
year=199
url="https://google.de,,,

sfdfs

asdasdasd={12312
}

asdasdasdasd asd oaskfdösdfr234r 243r wef

@book{sample2,
title={Buch ohne Autor},
year={2019},
}

@article{sample#3,
title={Unerwartete Zeichen im Schlüssel},
author={Autor 3},
year={2018},
}

@inproceedings{sample4,
title={Titel mit falschen "Anführungszeichen"},
author={Autor 4},
year={2017},
}

@online{sample5,
title={Ungültiges Feld},
author={Autor 5},
year={2021},
url="https://example.com",
publisher="Verlag 5",

sample1,
title={Fehlender Schlüssel},
author={Autor 1},
year={2022},
url="https://example.com",
}

@book{sample6,
title={Buch mit fehlendem Jahr},
author={Autor 6},
url="https://example.com",
}

@journal{sample7,
title={Artikel mit falschem Eintragstyp},
author={Autor 7},
year={2015},
}

@article{sample8,
title={Artikel mit Sonderzeichen wie !@# in Titel},
author={Autor 8},
year={2016},
}

@book{sample9,
title={Buch 1},
author={Autor 9},
year={2020},
}

@book{sample9,
title={Buch 2},
author={Autor 10},
year={2021},
}

@online{sample10,
title={Online-Ressource mit unvollständiger URL},
author={Autor 11},
year={2019},
url="example.com",
}
fsdfsdfd
</textarea>
<button onclick="parseBibtex()">Parse</button>

<h1>JSON</h1>
<pre id="outputDiv"></pre>
<h1>BibTeX</h1>
<pre id="bibtexDiv"></pre>
<div id="errorDiv" style="color: red;"></div>

<script>
function parseBibtex() {
try {
const bibtexInput = document.getElementById('bibtexInput').value;
const parsedJSON = bibtexParse.toJSON(bibtexInput);

if (parsedJSON) {
const prettyJSON = JSON.stringify(parsedJSON, null, 2);
document.getElementById('outputDiv').textContent = prettyJSON;
document.getElementById('bibtexDiv').textContent = bibtexParse.toBibtex(parsedJSON, 0);
document.getElementById('errorDiv').textContent = "";
return parsedJSON;
} else {
document.getElementById('outputDiv').textContent = "Invalid BibTeX input.";
document.getElementById('bibtexDiv').textContent = "";
document.getElementById('errorDiv').textContent = "";
}
} catch (error) {
console.warn("Error parsing BibTeX:", error);
document.getElementById('outputDiv').textContent = "An error occurred while parsing the input.";
document.getElementById('bibtexDiv').textContent = "";
document.getElementById('errorDiv').textContent = "Error: " + error.message;
}

return {};
}
</script>
</body>
</html>