@retorquere/bibtex-parser 8.0.5 → 8.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +36 -27
- package/index.js +73 -27
- package/package.json +1 -1
- package/verbatim.d.ts +0 -1
- package/verbatim.js +4 -5
package/index.d.ts
CHANGED
|
@@ -1,7 +1,43 @@
|
|
|
1
1
|
import { Node } from '@unified-latex/unified-latex-types';
|
|
2
2
|
import * as bibtex from './verbatim';
|
|
3
3
|
import * as JabRef from './jabref';
|
|
4
|
+
export { JabRefMetadata } from './jabref';
|
|
4
5
|
export { toSentenceCase } from './sentence-case';
|
|
6
|
+
type CreatorFields = {
|
|
7
|
+
author?: Creator[];
|
|
8
|
+
bookauthor?: Creator[];
|
|
9
|
+
collaborator?: Creator[];
|
|
10
|
+
commentator?: Creator[];
|
|
11
|
+
director?: Creator[];
|
|
12
|
+
editor?: Creator[];
|
|
13
|
+
editora?: Creator[];
|
|
14
|
+
editorb?: Creator[];
|
|
15
|
+
editors?: Creator[];
|
|
16
|
+
holder?: Creator[];
|
|
17
|
+
scriptwriter?: Creator[];
|
|
18
|
+
translator?: Creator[];
|
|
19
|
+
};
|
|
20
|
+
type ArrayFields = {
|
|
21
|
+
keywords?: string[];
|
|
22
|
+
institution?: string[];
|
|
23
|
+
publisher?: string[];
|
|
24
|
+
origpublisher?: string[];
|
|
25
|
+
organization?: string[];
|
|
26
|
+
location?: string[];
|
|
27
|
+
origlocation?: string[];
|
|
28
|
+
};
|
|
29
|
+
type NumberFields = {
|
|
30
|
+
year?: number | string;
|
|
31
|
+
month?: number | string;
|
|
32
|
+
};
|
|
33
|
+
type TypedFields = CreatorFields & ArrayFields & NumberFields;
|
|
34
|
+
type Fields = TypedFields & Omit<Record<string, string>, keyof TypedFields>;
|
|
35
|
+
export type Entry = {
|
|
36
|
+
type: string;
|
|
37
|
+
key: string;
|
|
38
|
+
fields: Fields;
|
|
39
|
+
input: string;
|
|
40
|
+
};
|
|
5
41
|
export interface Bibliography {
|
|
6
42
|
/**
|
|
7
43
|
* errors found while parsing
|
|
@@ -134,38 +170,11 @@ export interface Creator {
|
|
|
134
170
|
useprefix?: boolean;
|
|
135
171
|
juniorcomma?: boolean;
|
|
136
172
|
}
|
|
137
|
-
export interface Entry {
|
|
138
|
-
type: string;
|
|
139
|
-
key: string;
|
|
140
|
-
fields: {
|
|
141
|
-
author?: Creator[];
|
|
142
|
-
bookauthor?: Creator[];
|
|
143
|
-
collaborator?: Creator[];
|
|
144
|
-
commentator?: Creator[];
|
|
145
|
-
director?: Creator[];
|
|
146
|
-
editor?: Creator[];
|
|
147
|
-
editora?: Creator[];
|
|
148
|
-
editorb?: Creator[];
|
|
149
|
-
editors?: Creator[];
|
|
150
|
-
holder?: Creator[];
|
|
151
|
-
scriptwriter?: Creator[];
|
|
152
|
-
translator?: Creator[];
|
|
153
|
-
keywords?: string[];
|
|
154
|
-
institution?: string[];
|
|
155
|
-
publisher?: string[];
|
|
156
|
-
origpublisher?: string[];
|
|
157
|
-
organization?: string[];
|
|
158
|
-
location?: string[];
|
|
159
|
-
origlocation?: string[];
|
|
160
|
-
[key: string]: number | string | string[] | Creator[];
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
173
|
export declare const FieldMode: {
|
|
164
174
|
creator: string[];
|
|
165
175
|
title: string[];
|
|
166
176
|
verbatim: (string | RegExp)[];
|
|
167
177
|
richtext: string[];
|
|
168
|
-
commalist: string[];
|
|
169
178
|
literallist: string[];
|
|
170
179
|
};
|
|
171
180
|
type ParseMode = keyof typeof FieldMode | 'literal';
|
package/index.js
CHANGED
|
@@ -76,6 +76,31 @@ for (const tag of ['i', 'b', 'sc', 'nc', 'ncx', 'br', 'p', 'li', 'code']) {
|
|
|
76
76
|
close[tag] = `\x0E/${tag}\x0F`;
|
|
77
77
|
}
|
|
78
78
|
const collapsable = /\x0E\/([a-z]+)\x0F(\s*)\x0E\1\x0F/ig;
|
|
79
|
+
const Month = {
|
|
80
|
+
jan: 1,
|
|
81
|
+
january: 1,
|
|
82
|
+
feb: 2,
|
|
83
|
+
february: 2,
|
|
84
|
+
mar: 3,
|
|
85
|
+
march: 3,
|
|
86
|
+
apr: 4,
|
|
87
|
+
april: 4,
|
|
88
|
+
may: 5,
|
|
89
|
+
jun: 6,
|
|
90
|
+
june: 6,
|
|
91
|
+
jul: 7,
|
|
92
|
+
july: 7,
|
|
93
|
+
aug: 8,
|
|
94
|
+
august: 8,
|
|
95
|
+
sep: 9,
|
|
96
|
+
september: 9,
|
|
97
|
+
oct: 10,
|
|
98
|
+
october: 10,
|
|
99
|
+
nov: 11,
|
|
100
|
+
november: 11,
|
|
101
|
+
dec: 12,
|
|
102
|
+
december: 12,
|
|
103
|
+
};
|
|
79
104
|
exports.FieldMode = {
|
|
80
105
|
creator: [
|
|
81
106
|
'author',
|
|
@@ -114,6 +139,7 @@ exports.FieldMode = {
|
|
|
114
139
|
'verba',
|
|
115
140
|
'verbb',
|
|
116
141
|
'verbc',
|
|
142
|
+
/^keywords([+]duplicate-\d+)?$/,
|
|
117
143
|
/^citeulike-linkout-[0-9]+$/,
|
|
118
144
|
/^bdsk-url-[0-9]+$/,
|
|
119
145
|
],
|
|
@@ -125,9 +151,6 @@ exports.FieldMode = {
|
|
|
125
151
|
'notes',
|
|
126
152
|
'note',
|
|
127
153
|
],
|
|
128
|
-
commalist: [
|
|
129
|
-
'keywords',
|
|
130
|
-
],
|
|
131
154
|
literallist: [
|
|
132
155
|
'institution',
|
|
133
156
|
'publisher',
|
|
@@ -250,6 +273,7 @@ function asyncGenerator(array) {
|
|
|
250
273
|
class BibTeXParser {
|
|
251
274
|
constructor() {
|
|
252
275
|
this.newcommands = {};
|
|
276
|
+
this.unhandled = new Set;
|
|
253
277
|
}
|
|
254
278
|
split(ast, sep, split) {
|
|
255
279
|
const roots = [];
|
|
@@ -412,19 +436,30 @@ class BibTeXParser {
|
|
|
412
436
|
}
|
|
413
437
|
unsupported(node) {
|
|
414
438
|
var _a;
|
|
439
|
+
const tex = (0, unified_latex_util_print_raw_1.printRaw)(node);
|
|
415
440
|
if (this.fallback)
|
|
416
|
-
return (_a = this.fallback(node,
|
|
441
|
+
return (_a = this.fallback(node, tex, this.current)) !== null && _a !== void 0 ? _a : '';
|
|
442
|
+
let id;
|
|
417
443
|
switch (node.type) {
|
|
418
444
|
case 'macro':
|
|
419
|
-
|
|
445
|
+
id = `${node.type}.${node.content}`;
|
|
446
|
+
if (!this.unhandled.has(id)) {
|
|
447
|
+
this.unhandled.add(id);
|
|
448
|
+
this.bib.errors.push({ error: `unhandled ${node.type} ${(0, unified_latex_util_print_raw_1.printRaw)(node)}`, input: (0, unified_latex_util_print_raw_1.printRaw)(node) });
|
|
449
|
+
}
|
|
420
450
|
break;
|
|
421
451
|
case 'environment':
|
|
422
|
-
|
|
452
|
+
id = `${node.type}.${node.env}`;
|
|
453
|
+
if (!this.unhandled.has(id)) {
|
|
454
|
+
this.unhandled.add(id);
|
|
455
|
+
this.bib.errors.push({ error: `unhandled ${node.type} ${node.env} (${(0, unified_latex_util_print_raw_1.printRaw)(node)})`, input: (0, unified_latex_util_print_raw_1.printRaw)(node) });
|
|
456
|
+
}
|
|
423
457
|
break;
|
|
424
458
|
default:
|
|
425
459
|
this.bib.errors.push({ error: `unhandled ${node.type} (${(0, unified_latex_util_print_raw_1.printRaw)(node)})`, input: (0, unified_latex_util_print_raw_1.printRaw)(node) });
|
|
426
460
|
break;
|
|
427
461
|
}
|
|
462
|
+
return tex;
|
|
428
463
|
}
|
|
429
464
|
wrap(text, tag, wrap = true) {
|
|
430
465
|
if (!text || !wrap)
|
|
@@ -878,15 +913,16 @@ class BibTeXParser {
|
|
|
878
913
|
});
|
|
879
914
|
switch (mode) {
|
|
880
915
|
case 'creator':
|
|
881
|
-
entry.fields[field] = this.split(ast, /^and$/i, /(^& | & | &$)/)
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
entry.fields[field] = this.split(ast, /^[;,]$/, /(&)/).map(elt => this.stringify(elt, { mode: 'literal' }).trim());
|
|
916
|
+
entry.fields[field] = this.split(ast, /^and$/i, /(^& | & | &$)/)
|
|
917
|
+
.map(cr => this.parseCreator(cr))
|
|
918
|
+
.filter(cr => Object.keys(cr).length); // pacify typescript
|
|
885
919
|
break;
|
|
886
920
|
case 'literallist':
|
|
887
|
-
entry.fields[field] = this.split(ast, /^and$/i, /(^& | & | &$)/)
|
|
921
|
+
entry.fields[field] = this.split(ast, /^and$/i, /(^& | & | &$)/)
|
|
922
|
+
.map(elt => this.stringify(elt, { mode: 'literal' }).trim()); // pacify typescript
|
|
888
923
|
break;
|
|
889
924
|
default:
|
|
925
|
+
// can be number or string, but typescript cannot know this
|
|
890
926
|
entry.fields[field] = this.stringField(field, this.stringify(ast, { mode }), sentenceCase, mode);
|
|
891
927
|
break;
|
|
892
928
|
}
|
|
@@ -937,31 +973,41 @@ class BibTeXParser {
|
|
|
937
973
|
jabref: null,
|
|
938
974
|
};
|
|
939
975
|
}
|
|
940
|
-
reparse(
|
|
941
|
-
let langid = (
|
|
942
|
-
if (!langid && this.options.sentenceCase.language &&
|
|
943
|
-
langid =
|
|
976
|
+
reparse(verbatim) {
|
|
977
|
+
let langid = (verbatim.fields.langid || verbatim.fields.hyphenation || '').toLowerCase();
|
|
978
|
+
if (!langid && this.options.sentenceCase.language && verbatim.fields.language)
|
|
979
|
+
langid = verbatim.fields.language.toLowerCase();
|
|
944
980
|
const sentenceCase = this.options.sentenceCase.langids.includes(langid);
|
|
945
|
-
this.current =
|
|
981
|
+
const entry = this.current = {
|
|
982
|
+
type: verbatim.type,
|
|
983
|
+
key: verbatim.key,
|
|
984
|
+
fields: {},
|
|
985
|
+
input: verbatim.input,
|
|
986
|
+
};
|
|
946
987
|
let keywords = []; // OMG #783
|
|
947
988
|
try {
|
|
948
|
-
for (
|
|
949
|
-
if (!value.trim())
|
|
950
|
-
delete entry.fields[field];
|
|
989
|
+
for (let [field, value] of Object.entries(verbatim.fields)) {
|
|
990
|
+
if (!value.trim())
|
|
951
991
|
continue;
|
|
952
|
-
|
|
953
|
-
|
|
992
|
+
if (this.options.raw) {
|
|
993
|
+
entry.fields[field] = value.trim();
|
|
954
994
|
continue;
|
|
995
|
+
}
|
|
996
|
+
if (field.match(/^keywords([+]duplicate-\d+)?$/))
|
|
997
|
+
field = 'keywords'; // #873
|
|
955
998
|
this.field(entry, field, value, sentenceCase);
|
|
956
|
-
if (field
|
|
957
|
-
keywords = [...keywords, entry.fields[
|
|
958
|
-
delete entry.fields
|
|
999
|
+
if (field === 'keywords') { // #873
|
|
1000
|
+
keywords = [...keywords, ...entry.fields.keywords.split(/\s*[,;]\s*/)].map((k) => k.trim()).filter(k => k);
|
|
1001
|
+
delete entry.fields.keywords;
|
|
959
1002
|
}
|
|
960
|
-
if (typeof entry.fields[field] === 'string')
|
|
1003
|
+
if (typeof entry.fields[field] === 'string') {
|
|
961
1004
|
entry.fields[field] = entry.fields[field].trim();
|
|
1005
|
+
if (field === 'month')
|
|
1006
|
+
entry.fields[field] = Month[entry.fields[field].toLowerCase()] || entry.fields[field];
|
|
1007
|
+
}
|
|
962
1008
|
}
|
|
963
1009
|
if (keywords.length)
|
|
964
|
-
entry.fields.keywords = [...(new Set(
|
|
1010
|
+
entry.fields.keywords = [...(new Set(keywords))].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
965
1011
|
this.bib.entries.push(entry);
|
|
966
1012
|
}
|
|
967
1013
|
catch (err) {
|
|
@@ -969,7 +1015,7 @@ class BibTeXParser {
|
|
|
969
1015
|
}
|
|
970
1016
|
}
|
|
971
1017
|
content(tex) {
|
|
972
|
-
const entry = { key: '', type: '', fields: {} };
|
|
1018
|
+
const entry = { key: '', type: '', fields: {}, input: tex };
|
|
973
1019
|
this.field(entry, 'tex', tex, false);
|
|
974
1020
|
return entry.fields.tex;
|
|
975
1021
|
}
|
package/package.json
CHANGED
package/verbatim.d.ts
CHANGED
package/verbatim.js
CHANGED
|
@@ -85,7 +85,6 @@ class Parser {
|
|
|
85
85
|
this.max_entries = options.max_entries || 0;
|
|
86
86
|
this.input = input;
|
|
87
87
|
this.parsing = null;
|
|
88
|
-
this.keywords = 0;
|
|
89
88
|
if (typeof options.strings === 'string') {
|
|
90
89
|
this.input = options.strings + '\n' + input; // eslint-disable-line prefer-template
|
|
91
90
|
}
|
|
@@ -271,10 +270,10 @@ class Parser {
|
|
|
271
270
|
this.strings[key.toUpperCase()] = val;
|
|
272
271
|
}
|
|
273
272
|
else {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
const bare = key.toLowerCase();
|
|
274
|
+
let postfix = 0;
|
|
275
|
+
while (typeof this.entries[0].fields[key = (postfix ? `${bare}+duplicate-${postfix}` : bare)] === 'string') {
|
|
276
|
+
postfix++;
|
|
278
277
|
}
|
|
279
278
|
this.entries[0].fields[key] = val;
|
|
280
279
|
}
|