@retorquere/bibtex-parser 12.1.10 → 12.1.11
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/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/jabref.js +31 -7
- package/dist/cjs/jabref.js.map +2 -2
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/jabref.js +42 -7
- package/dist/esm/jabref.js.map +2 -2
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/jabref.d.ts +5 -9
- package/dist/types/jabref.d.ts.map +1 -1
- package/dist/wasm/bibtex_parser_bg.wasm +0 -0
- package/dist/wasm/index.d.ts +3 -14
- package/dist/wasm/index.js +10 -4
- package/dist/wasm/jabref.d.ts +53 -0
- package/dist/wasm/jabref.js +133 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jabref.d.ts","sourceRoot":"","sources":["../../jabref.ts"],"names":[],"mappings":"AAuBA;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAA;IAEjB;;OAEG;IACH,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB;AAED,
|
|
1
|
+
{"version":3,"file":"jabref.d.ts","sourceRoot":"","sources":["../../jabref.ts"],"names":[],"mappings":"AAuBA;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAA;IAEjB;;OAEG;IACH,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB;AAED,qBAAa,cAAc;;IAGzB;;OAEG;IACH,IAAI,EAAE,KAAK,EAAE,CAAK;IAElB;;OAEG;IACK,aAAa,CAAC,EAAE,MAAM,CAAA;IAE9B;;OAEG;IACK,aAAa,CAAC,EAAE,MAAM,CAAA;IAE9B;;OAEG;IACK,YAAY,CAAC,EAAE,MAAM,CAAA;gBAEjB,IAAI,GAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,eAAe,GAAG,eAAe,GAAG,cAAc,CAAC,CAAM;IAcjH,wGAAwG;IACxG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;CAM7C;AAED;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAgFxF"}
|
|
Binary file
|
package/dist/wasm/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/** @module wasm */
|
|
2
2
|
import init, { initSync } from './bibtex_parser.js';
|
|
3
|
+
import { JabRefMetadata } from './jabref.js';
|
|
4
|
+
export { JabRefMetadata };
|
|
5
|
+
export type { Group as JabRefGroup } from './jabref.js';
|
|
3
6
|
export type { InitInput, InitOutput, SyncInitInput } from './bibtex_parser.js';
|
|
4
7
|
/** Initializes the WebAssembly parser; await this before using its exports. */
|
|
5
8
|
export { init, initSync };
|
|
@@ -60,20 +63,6 @@ export interface ParseError {
|
|
|
60
63
|
error: string;
|
|
61
64
|
input?: string;
|
|
62
65
|
}
|
|
63
|
-
/** A group in JabRef's nested group hierarchy. */
|
|
64
|
-
export interface JabRefGroup {
|
|
65
|
-
name: string;
|
|
66
|
-
entries: string[];
|
|
67
|
-
groups: JabRefGroup[];
|
|
68
|
-
}
|
|
69
|
-
/** JabRef metadata extracted from a BibTeX library. */
|
|
70
|
-
export interface JabRefMetadata {
|
|
71
|
-
root: JabRefGroup[];
|
|
72
|
-
groups: Record<string, JabRefGroup>;
|
|
73
|
-
fileDirectory?: string;
|
|
74
|
-
groupsversion?: number;
|
|
75
|
-
databaseType?: string;
|
|
76
|
-
}
|
|
77
66
|
/** The parsed contents of a BibTeX library. */
|
|
78
67
|
export interface Library {
|
|
79
68
|
errors: ParseError[];
|
package/dist/wasm/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** @module wasm */
|
|
2
2
|
import init, { initSync, parse as parseWasm, parseAsync as parseAsyncWasm, parseVerbatim as parseVerbatimWasm, parseVerbatimAsync as parseVerbatimAsyncWasm, tokenize as tokenizeWasm, toSentenceCase as toSentenceCaseWasm } from './bibtex_parser.js';
|
|
3
|
+
import { JabRefMetadata } from './jabref.js';
|
|
4
|
+
export { JabRefMetadata };
|
|
3
5
|
/** Initializes the WebAssembly parser; await this before using its exports. */
|
|
4
6
|
export { init, initSync };
|
|
5
7
|
export default init;
|
|
@@ -57,20 +59,24 @@ function throwOnUnsupported(result) {
|
|
|
57
59
|
throw new Error(unsupported.error);
|
|
58
60
|
return result;
|
|
59
61
|
}
|
|
62
|
+
function withJabRef(result) {
|
|
63
|
+
result.jabref = new JabRefMetadata(result.jabref);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
60
66
|
/** Parses BibTeX while leaving field contents uninterpreted. */
|
|
61
67
|
export function parseVerbatim(input, options = {}) {
|
|
62
68
|
const prepared = prepare(input, options);
|
|
63
|
-
return parseVerbatimWasm(prepared.input, prepared.options);
|
|
69
|
+
return withJabRef(parseVerbatimWasm(prepared.input, prepared.options));
|
|
64
70
|
}
|
|
65
71
|
/** Asynchronous variant of {@link parseVerbatim}. */
|
|
66
72
|
export async function parseVerbatimAsync(input, options = {}) {
|
|
67
73
|
const prepared = prepare(input, options);
|
|
68
|
-
return await parseVerbatimAsyncWasm(prepared.input, prepared.options);
|
|
74
|
+
return withJabRef(await parseVerbatimAsyncWasm(prepared.input, prepared.options));
|
|
69
75
|
}
|
|
70
76
|
/** Parses BibTeX or BibLaTeX source into a normalized library. */
|
|
71
77
|
export function parse(input, options = {}) {
|
|
72
78
|
const prepared = prepare(input, options);
|
|
73
|
-
const result = parseWasm(prepared.input, prepared.options);
|
|
79
|
+
const result = withJabRef(parseWasm(prepared.input, prepared.options));
|
|
74
80
|
if (options.unsupported === 'throw')
|
|
75
81
|
return throwOnUnsupported(result);
|
|
76
82
|
return result;
|
|
@@ -78,7 +84,7 @@ export function parse(input, options = {}) {
|
|
|
78
84
|
/** Asynchronous variant of {@link parse}, yielding during large parses. */
|
|
79
85
|
export async function parseAsync(input, options = {}) {
|
|
80
86
|
const prepared = prepare(input, options);
|
|
81
|
-
const result = await parseAsyncWasm(prepared.input, prepared.options);
|
|
87
|
+
const result = withJabRef(await parseAsyncWasm(prepared.input, prepared.options));
|
|
82
88
|
if (options.unsupported === 'throw')
|
|
83
89
|
return throwOnUnsupported(result);
|
|
84
90
|
return result;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A JabRef group.
|
|
3
|
+
*/
|
|
4
|
+
export interface Group {
|
|
5
|
+
/**
|
|
6
|
+
* the group name
|
|
7
|
+
*/
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* The citation keys which are specified to belong to this group, after intersection calculation has been applied
|
|
11
|
+
*/
|
|
12
|
+
entries: string[];
|
|
13
|
+
/**
|
|
14
|
+
* Sub-groups under this group
|
|
15
|
+
*/
|
|
16
|
+
groups: Group[];
|
|
17
|
+
}
|
|
18
|
+
export declare class JabRefMetadata {
|
|
19
|
+
#private;
|
|
20
|
+
/**
|
|
21
|
+
* The root groups. You can find the nested groups in their `groups` property
|
|
22
|
+
*/
|
|
23
|
+
root: Group[];
|
|
24
|
+
/**
|
|
25
|
+
* The base path for file paths
|
|
26
|
+
*/
|
|
27
|
+
fileDirectory?: string;
|
|
28
|
+
/**
|
|
29
|
+
* The JabRef metadata format version
|
|
30
|
+
*/
|
|
31
|
+
groupsversion?: number;
|
|
32
|
+
/**
|
|
33
|
+
* The JabRef metadata database type
|
|
34
|
+
*/
|
|
35
|
+
databaseType?: string;
|
|
36
|
+
constructor(data?: Partial<Pick<JabRefMetadata, 'root' | 'fileDirectory' | 'groupsversion' | 'databaseType'>>);
|
|
37
|
+
/** Populates JabRef 3.8+ memberships in `root` by group name; duplicate names select the first node. */
|
|
38
|
+
addEntry(name: string, key: string): boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Import the JabRef groups from the `@string` comments in which they were stored. You would typically pass the comments parsed by [[bibtex.parse]] in here.
|
|
42
|
+
*
|
|
43
|
+
* JabRef knows several group types, and this parser parses most, but not all of them:
|
|
44
|
+
*
|
|
45
|
+
* * independent group: the keys listed in the group are the entries that are considered to belong to it
|
|
46
|
+
* * intersection: the keys listed in the group are considered to belong to the group if they're also in the parent group
|
|
47
|
+
* * union: the keys listed in the group are considered to belong to the group, and also the keys that are in the parent group
|
|
48
|
+
* * query: not supported by this parser
|
|
49
|
+
*/
|
|
50
|
+
export declare function parse(comments: string[]): {
|
|
51
|
+
comments: string[];
|
|
52
|
+
jabref: JabRefMetadata;
|
|
53
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
function decode(s = '', sep = ';') {
|
|
2
|
+
s = s.replace(/\r?\n/g, '');
|
|
3
|
+
let pos = 0;
|
|
4
|
+
const records = [''];
|
|
5
|
+
while (pos < s.length) {
|
|
6
|
+
switch (s[pos]) {
|
|
7
|
+
case '\\':
|
|
8
|
+
pos++;
|
|
9
|
+
records[0] += s[pos];
|
|
10
|
+
break;
|
|
11
|
+
case sep:
|
|
12
|
+
records.unshift('');
|
|
13
|
+
break;
|
|
14
|
+
default:
|
|
15
|
+
records[0] += s[pos];
|
|
16
|
+
}
|
|
17
|
+
pos++;
|
|
18
|
+
}
|
|
19
|
+
return records.reverse().filter(record => record);
|
|
20
|
+
}
|
|
21
|
+
export class JabRefMetadata {
|
|
22
|
+
#groups = new Map();
|
|
23
|
+
/**
|
|
24
|
+
* The root groups. You can find the nested groups in their `groups` property
|
|
25
|
+
*/
|
|
26
|
+
root = [];
|
|
27
|
+
constructor(data = {}) {
|
|
28
|
+
this.root = data.root ?? [];
|
|
29
|
+
for (const field of ['fileDirectory', 'groupsversion', 'databaseType']) {
|
|
30
|
+
if (data[field] !== undefined)
|
|
31
|
+
Object.assign(this, { [field]: data[field] });
|
|
32
|
+
}
|
|
33
|
+
const index = (groups) => {
|
|
34
|
+
for (const group of groups) {
|
|
35
|
+
if (!this.#groups.has(group.name))
|
|
36
|
+
this.#groups.set(group.name, group);
|
|
37
|
+
index(group.groups);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
index(this.root);
|
|
41
|
+
}
|
|
42
|
+
/** Populates JabRef 3.8+ memberships in `root` by group name; duplicate names select the first node. */
|
|
43
|
+
addEntry(name, key) {
|
|
44
|
+
const group = this.#groups.get(name);
|
|
45
|
+
if (!group)
|
|
46
|
+
return false;
|
|
47
|
+
if (!group.entries.includes(key))
|
|
48
|
+
group.entries.push(key);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Import the JabRef groups from the `@string` comments in which they were stored. You would typically pass the comments parsed by [[bibtex.parse]] in here.
|
|
54
|
+
*
|
|
55
|
+
* JabRef knows several group types, and this parser parses most, but not all of them:
|
|
56
|
+
*
|
|
57
|
+
* * independent group: the keys listed in the group are the entries that are considered to belong to it
|
|
58
|
+
* * intersection: the keys listed in the group are considered to belong to the group if they're also in the parent group
|
|
59
|
+
* * union: the keys listed in the group are considered to belong to the group, and also the keys that are in the parent group
|
|
60
|
+
* * query: not supported by this parser
|
|
61
|
+
*/
|
|
62
|
+
export function parse(comments) {
|
|
63
|
+
const result = new JabRefMetadata();
|
|
64
|
+
const levels = [];
|
|
65
|
+
const decoded = {
|
|
66
|
+
fileDirectory: null,
|
|
67
|
+
groupsversion: null,
|
|
68
|
+
groupstree: null,
|
|
69
|
+
grouping: null,
|
|
70
|
+
databaseType: null,
|
|
71
|
+
};
|
|
72
|
+
comments = comments.filter(comment => {
|
|
73
|
+
const m = comment.match(/^jabref-meta:\s*([^:]+):([\s\S]*)/); // use \s\S because mozilla doesn't understand /s
|
|
74
|
+
if (m) {
|
|
75
|
+
decoded[m[1]] = decode(m[2]);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
if (decoded.groupsversion)
|
|
81
|
+
result.groupsversion = parseInt(decoded.groupsversion[0].trim()); // eslint-disable-line @typescript-eslint/no-unsafe-argument
|
|
82
|
+
if (decoded.fileDirectory)
|
|
83
|
+
result.fileDirectory = decoded.fileDirectory[0];
|
|
84
|
+
if (decoded.databaseType)
|
|
85
|
+
result.databaseType = decoded.databaseType[0];
|
|
86
|
+
for (const tree of ['groupstree', 'grouping']) {
|
|
87
|
+
if (!decoded[tree])
|
|
88
|
+
continue;
|
|
89
|
+
for (const encoded of decoded[tree]) {
|
|
90
|
+
const fields = decode(encoded);
|
|
91
|
+
const level_type_name = decode(fields.shift(), ':');
|
|
92
|
+
const m = /^([0-9]+) (.+)/.exec(level_type_name[0]);
|
|
93
|
+
if (!m)
|
|
94
|
+
break;
|
|
95
|
+
const level = parseInt(m[1]);
|
|
96
|
+
const type = m[2]; // test for StaticGroup?
|
|
97
|
+
if (type === 'AllEntriesGroup')
|
|
98
|
+
continue; // root
|
|
99
|
+
const name = level_type_name[1];
|
|
100
|
+
const intersection = decode(fields.shift())[0];
|
|
101
|
+
const keys = tree === 'grouping' ? [] : fields.map(field => decode(field)[0]);
|
|
102
|
+
const group = {
|
|
103
|
+
name,
|
|
104
|
+
entries: keys,
|
|
105
|
+
groups: [],
|
|
106
|
+
};
|
|
107
|
+
if (levels.length < level) {
|
|
108
|
+
levels.push(group);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
levels[level - 1] = group;
|
|
112
|
+
}
|
|
113
|
+
if (level === 1) {
|
|
114
|
+
result.root.push(group);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const parent = levels[level - 2];
|
|
118
|
+
switch (intersection) {
|
|
119
|
+
case '0': // independent
|
|
120
|
+
break;
|
|
121
|
+
case '1': // intersect
|
|
122
|
+
group.entries = group.entries.filter(key => parent.entries.includes(key));
|
|
123
|
+
break;
|
|
124
|
+
case '2': // union
|
|
125
|
+
group.entries = group.entries.concat(parent.entries.filter(key => !group.entries.includes(key)));
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
levels[level - 2].groups.push(group);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { comments, jabref: new JabRefMetadata(result) };
|
|
133
|
+
}
|