@retorquere/bibtex-parser 13.0.3 → 13.0.5

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.
Binary file
@@ -1,8 +1,5 @@
1
1
  /** @module @retorquere/bibtex-parser */
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';
6
3
  /** Inputs for asynchronous WASM initialization: a URL-like resource to fetch, bytes, or a compiled module. */
7
4
  export type { InitInput } from './bibtex_parser.js';
8
5
  /** Inputs for synchronous WASM initialization: bytes or a compiled module; synchronous initialization cannot fetch a URL. */
@@ -115,6 +112,19 @@ export interface ParseError {
115
112
  /** Source fragment associated with the diagnostic, when available. */
116
113
  input?: string;
117
114
  }
115
+ /** A JabRef group serialized by the Rust parser. */
116
+ export interface JabRefGroup {
117
+ name: string;
118
+ entries: string[];
119
+ groups: JabRefGroup[];
120
+ }
121
+ /** JabRef metadata serialized by the Rust parser. */
122
+ export interface JabRefMetadata {
123
+ root: JabRefGroup[];
124
+ fileDirectory?: string;
125
+ groupsversion?: number;
126
+ databaseType?: string;
127
+ }
118
128
  /** The parsed contents of a BibTeX library. */
119
129
  export interface Library {
120
130
  /** Diagnostics collected while parsing; recoverable errors do not necessarily prevent entries from being returned. */
@@ -1,8 +1,6 @@
1
1
  /** @module @retorquere/bibtex-parser */
2
2
  import init, { initSync, parse as parseWasm, parseAsync as parseAsyncWasm, parseVerbatim as parseVerbatimWasm, parseVerbatimAsync as parseVerbatimAsyncWasm, toSentenceCase as toSentenceCaseWasm } from './bibtex_parser.js';
3
- import { JabRefMetadata } from './jabref.js';
4
3
  import englishDefaults from './english.json' with { type: 'json' };
5
- export { JabRefMetadata };
6
4
  /**
7
5
  * Loads and initializes the WebAssembly parser asynchronously.
8
6
  *
@@ -51,10 +49,6 @@ function throwOnUnsupported(result) {
51
49
  throw new Error(unsupported.error);
52
50
  return result;
53
51
  }
54
- function withJabRef(result) {
55
- result.jabref = new JabRefMetadata(result.jabref);
56
- return result;
57
- }
58
52
  /**
59
53
  * Parses BibTeX without converting LaTeX field contents to Unicode or structured creator values.
60
54
  * `@string` references are resolved, while each entry's fields remain strings for later processing.
@@ -86,7 +80,7 @@ export async function parseVerbatimAsync(input, options = {}) {
86
80
  */
87
81
  export function parse(input, options = {}) {
88
82
  const prepared = prepare(input, options);
89
- const result = withJabRef(parseWasm(prepared.input, prepared.options));
83
+ const result = parseWasm(prepared.input, prepared.options);
90
84
  if (options.unsupported === 'throw')
91
85
  return throwOnUnsupported(result);
92
86
  return result;
@@ -94,7 +88,7 @@ export function parse(input, options = {}) {
94
88
  /** Asynchronous variant of {@link parse}; returns the same result shape and yields between batches for large inputs. */
95
89
  export async function parseAsync(input, options = {}) {
96
90
  const prepared = prepare(input, options);
97
- const result = withJabRef(await parseAsyncWasm(prepared.input, prepared.options));
91
+ const result = await parseAsyncWasm(prepared.input, prepared.options);
98
92
  if (options.unsupported === 'throw')
99
93
  return throwOnUnsupported(result);
100
94
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retorquere/bibtex-parser",
3
- "version": "13.0.3",
3
+ "version": "13.0.5",
4
4
  "description": "BibTeX parser",
5
5
  "type": "module",
6
6
  "module": "./dist/wasm/index.js",
@@ -38,8 +38,8 @@
38
38
  "pretest:js": "npm run build:ts",
39
39
  "test:js": "node test/js.js",
40
40
  "pretest:all": "npm run build:all",
41
- "test:all": "npm run test:wasm && npm run test:js && node --test test/package.test.js",
42
- "test:release": "npm run test:wasm && node --test test/package.test.js",
41
+ "test:all": "npm run test:wasm && npm run test:js",
42
+ "test:release": "npm run test:wasm",
43
43
  "test:rust": "cargo test --manifest-path rust/Cargo.toml",
44
44
  "minitest": "./build/crossref.py && npm run build && node i.js",
45
45
  "list": "tar tvf $(npm pack)",
@@ -63,16 +63,16 @@
63
63
  "author": "Emiliano Heyns",
64
64
  "license": "ISC",
65
65
  "devDependencies": {
66
- "@types/node": "^26.6.5",
66
+ "@types/node": "^26.6.6",
67
67
  "@unified-latex/unified-latex-types": "^1.8.4",
68
68
  "command-line-args": "^6.0.2",
69
69
  "csv": "^6.6.4",
70
70
  "digital-tree": "^2.0.4",
71
- "dprint": "^0.63.0",
72
- "ejs": "^7.0.1",
71
+ "dprint": "^0.64.3",
72
+ "ejs": "^7.0.2",
73
73
  "esbuild": "^0.28.2",
74
- "glob": "^13.0.6",
75
- "js-yaml": "^5.4.3",
74
+ "glob": "^14.0.3",
75
+ "js-yaml": "^5.5.0",
76
76
  "minimist": "^1.2.8",
77
77
  "mkdirp": "^3.0.1",
78
78
  "node-fetch": "^3.3.2",
@@ -80,7 +80,7 @@
80
80
  "slug": "^12.0.1",
81
81
  "tap": "^21.8.0",
82
82
  "ts-node": "^10.9.2",
83
- "tslib": "^2.8.1",
83
+ "tslib": "^2.9.1",
84
84
  "typedoc": "^0.28.20",
85
85
  "typescript": "npm:@typescript/typescript6@^6.0.2"
86
86
  },
@@ -93,7 +93,7 @@
93
93
  "lodash.merge": "^4.6.2",
94
94
  "moo": "^0.5.3",
95
95
  "nearley": "^2.20.1",
96
- "unicode2latex": "^7.0.37",
96
+ "unicode2latex": "^7.0.38",
97
97
  "wink-eng-lite-web-model": "^1.8.1",
98
98
  "wink-nlp": "^2.4.0"
99
99
  },
@@ -107,6 +107,6 @@
107
107
  },
108
108
  "allowScripts": {
109
109
  "esbuild@0.28.2": true,
110
- "dprint@0.63.0": true
110
+ "dprint@0.64.3": true
111
111
  }
112
112
  }
@@ -1,41 +0,0 @@
1
- /**
2
- * A JabRef group.
3
- */
4
- export interface Group {
5
- /** Name displayed for this group in JabRef. */
6
- name: string;
7
- /** Citation keys belonging to this group after supported group rules are applied. */
8
- entries: string[];
9
- /** Direct child groups. */
10
- groups: Group[];
11
- }
12
- /** JabRef metadata parsed from a BibTeX library, including its group tree and file settings. */
13
- export declare class JabRefMetadata {
14
- #private;
15
- /** Top-level groups; nested groups are available through each group's `groups` property. */
16
- root: Group[];
17
- /** Base directory used to resolve relative attachment paths. */
18
- fileDirectory?: string;
19
- /** JabRef group metadata format version. */
20
- groupsversion?: number;
21
- /** Database type recorded in the JabRef metadata. */
22
- databaseType?: string;
23
- /** Creates metadata from parsed JabRef properties and indexes groups for membership updates. */
24
- constructor(data?: Partial<Pick<JabRefMetadata, 'root' | 'fileDirectory' | 'groupsversion' | 'databaseType'>>);
25
- /** Populates JabRef 3.8+ memberships in `root` by group name; duplicate names select the first node. */
26
- addEntry(name: string, key: string): boolean;
27
- }
28
- /**
29
- * 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.
30
- *
31
- * JabRef knows several group types, and this parser parses most, but not all of them:
32
- *
33
- * * independent group: the keys listed in the group are the entries that are considered to belong to it
34
- * * intersection: the keys listed in the group are considered to belong to the group if they're also in the parent group
35
- * * union: the keys listed in the group are considered to belong to the group, and also the keys that are in the parent group
36
- * * query: not supported by this parser
37
- */
38
- export declare function parse(comments: string[]): {
39
- comments: string[];
40
- jabref: JabRefMetadata;
41
- };
@@ -1,133 +0,0 @@
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
- /** JabRef metadata parsed from a BibTeX library, including its group tree and file settings. */
22
- export class JabRefMetadata {
23
- #groups = new Map();
24
- /** Top-level groups; nested groups are available through each group's `groups` property. */
25
- root = [];
26
- /** Creates metadata from parsed JabRef properties and indexes groups for membership updates. */
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
- }