@retorquere/bibtex-parser 9.0.21 → 9.0.24

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.
Files changed (81) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/crossref.js +209 -0
  3. package/dist/cjs/crossref.js.map +7 -0
  4. package/dist/cjs/fields.js +6961 -0
  5. package/dist/cjs/fields.js.map +7 -0
  6. package/dist/cjs/index.js +1072 -0
  7. package/dist/cjs/index.js.map +7 -0
  8. package/dist/cjs/jabref.js +111 -0
  9. package/dist/cjs/jabref.js.map +7 -0
  10. package/dist/cjs/merge.js +37 -0
  11. package/dist/cjs/merge.js.map +7 -0
  12. package/dist/cjs/prepositions.js +111 -0
  13. package/dist/cjs/prepositions.js.map +7 -0
  14. package/dist/cjs/sentence-case.js +98 -0
  15. package/dist/cjs/sentence-case.js.map +7 -0
  16. package/dist/cjs/tokenizer.js +194 -0
  17. package/dist/cjs/tokenizer.js.map +7 -0
  18. package/dist/cjs/verbatim.js +403 -0
  19. package/dist/cjs/verbatim.js.map +7 -0
  20. package/dist/cjs/yield.js +26 -0
  21. package/dist/cjs/yield.js.map +7 -0
  22. package/{crossref.json → dist/data/crossref.json} +1 -1
  23. package/{fields.json → dist/data/fields.json} +1 -1
  24. package/dist/esm/crossref.js +190 -0
  25. package/dist/esm/crossref.js.map +7 -0
  26. package/dist/esm/fields.js +6942 -0
  27. package/dist/esm/fields.js.map +7 -0
  28. package/dist/esm/index.js +1044 -0
  29. package/dist/esm/index.js.map +7 -0
  30. package/dist/esm/jabref.js +92 -0
  31. package/dist/esm/jabref.js.map +7 -0
  32. package/dist/esm/merge.js +8 -0
  33. package/dist/esm/merge.js.map +7 -0
  34. package/dist/esm/prepositions.js +92 -0
  35. package/dist/esm/prepositions.js.map +7 -0
  36. package/dist/esm/sentence-case.js +79 -0
  37. package/dist/esm/sentence-case.js.map +7 -0
  38. package/dist/esm/tokenizer.js +170 -0
  39. package/dist/esm/tokenizer.js.map +7 -0
  40. package/dist/esm/verbatim.js +387 -0
  41. package/dist/esm/verbatim.js.map +7 -0
  42. package/dist/esm/yield.js +7 -0
  43. package/dist/esm/yield.js.map +7 -0
  44. package/dist/types/crossref.d.ts +188 -0
  45. package/dist/types/crossref.d.ts.map +1 -0
  46. package/dist/types/fields.d.ts +55 -0
  47. package/dist/types/fields.d.ts.map +1 -0
  48. package/{index.d.ts → dist/types/index.d.ts} +8 -7
  49. package/dist/types/index.d.ts.map +1 -0
  50. package/dist/types/jabref.d.ts.map +1 -0
  51. package/dist/types/merge.d.ts.map +1 -0
  52. package/dist/types/prepositions.d.ts +3 -0
  53. package/dist/types/prepositions.d.ts.map +1 -0
  54. package/dist/types/sentence-case.d.ts.map +1 -0
  55. package/dist/types/tokenizer.d.ts.map +1 -0
  56. package/dist/types/verbatim.d.ts.map +1 -0
  57. package/dist/types/yield.d.ts.map +1 -0
  58. package/package.json +38 -47
  59. package/index.js +0 -1191
  60. package/index.js.map +0 -1
  61. package/jabref.js +0 -110
  62. package/jabref.js.map +0 -1
  63. package/merge.js +0 -11
  64. package/merge.js.map +0 -1
  65. package/sentence-case.js +0 -110
  66. package/sentence-case.js.map +0 -1
  67. package/tokenizer.js +0 -167
  68. package/tokenizer.js.map +0 -1
  69. package/verbatim.js +0 -430
  70. package/verbatim.js.map +0 -1
  71. package/yield.js +0 -7
  72. package/yield.js.map +0 -1
  73. /package/{prepositions.json → dist/data/prepositions.json} +0 -0
  74. /package/{strings.bib → dist/data/strings.bib} +0 -0
  75. /package/{unabbrev.json → dist/data/unabbrev.json} +0 -0
  76. /package/{jabref.d.ts → dist/types/jabref.d.ts} +0 -0
  77. /package/{merge.d.ts → dist/types/merge.d.ts} +0 -0
  78. /package/{sentence-case.d.ts → dist/types/sentence-case.d.ts} +0 -0
  79. /package/{tokenizer.d.ts → dist/types/tokenizer.d.ts} +0 -0
  80. /package/{verbatim.d.ts → dist/types/verbatim.d.ts} +0 -0
  81. /package/{yield.d.ts → dist/types/yield.d.ts} +0 -0
@@ -0,0 +1,1072 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var index_exports = {};
29
+ __export(index_exports, {
30
+ English: () => English,
31
+ FieldMode: () => FieldMode,
32
+ parse: () => parse,
33
+ parseAsync: () => parseAsync,
34
+ toSentenceCase: () => import_sentence_case2.toSentenceCase,
35
+ tokenize: () => import_tokenizer2.tokenize
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+ var import_unified_latex_util_pegjs = require("@unified-latex/unified-latex-util-pegjs");
39
+ var import_unified_latex_util_print_raw = require("@unified-latex/unified-latex-util-print-raw");
40
+ var import_unified_latex_util_replace = require("@unified-latex/unified-latex-util-replace");
41
+ var import_unified_latex_util_visit = require("@unified-latex/unified-latex-util-visit");
42
+ var import_unicode2latex = require("unicode2latex");
43
+ var JabRef = __toESM(require("./jabref.js"), 1);
44
+ var bibtex = __toESM(require("./verbatim.js"), 1);
45
+ var import_sentence_case = require("./sentence-case.js");
46
+ var import_sentence_case2 = require("./sentence-case.js");
47
+ var import_tokenizer = require("./tokenizer.js");
48
+ var import_tokenizer2 = require("./tokenizer.js");
49
+ var import_yield = require("./yield.js");
50
+ var import_crossref = __toESM(require("./crossref.js"), 1);
51
+ var import_fields = __toESM(require("./fields.js"), 1);
52
+ var import_merge = require("./merge.js");
53
+ function latexMode(node) {
54
+ return node._renderInfo.mode;
55
+ }
56
+ function latex2unicode(tex, node) {
57
+ const text = import_unicode2latex.latex2unicode[tex];
58
+ if (typeof text === "string") return text;
59
+ return text && text[latexMode(node)];
60
+ }
61
+ const open = {};
62
+ const close = {};
63
+ for (const tag of ["i", "b", "sc", "nc", "ncx", "br", "p", "li", "code"]) {
64
+ open[tag] = `${tag}`;
65
+ close[tag] = `/${tag}`;
66
+ }
67
+ const collapsable = /\x0E\/([a-z]+)\x0F(\s*)\x0E\1\x0F/ig;
68
+ const Month = {
69
+ jan: "1",
70
+ january: "1",
71
+ feb: "2",
72
+ february: "2",
73
+ mar: "3",
74
+ march: "3",
75
+ apr: "4",
76
+ april: "4",
77
+ may: "5",
78
+ jun: "6",
79
+ june: "6",
80
+ jul: "7",
81
+ july: "7",
82
+ aug: "8",
83
+ august: "8",
84
+ sep: "9",
85
+ september: "9",
86
+ oct: "10",
87
+ october: "10",
88
+ nov: "11",
89
+ november: "11",
90
+ dec: "12",
91
+ december: "12"
92
+ };
93
+ const FieldMode = {
94
+ creatorlist: [
95
+ "author",
96
+ "bookauthor",
97
+ "collaborator",
98
+ "commentator",
99
+ "director",
100
+ "editor",
101
+ "editora",
102
+ "editorb",
103
+ "editors",
104
+ "holder",
105
+ "scriptwriter",
106
+ "translator"
107
+ ],
108
+ title: [
109
+ "title",
110
+ "subtitle",
111
+ "series",
112
+ "shorttitle",
113
+ "booktitle",
114
+ // 'type',
115
+ "origtitle",
116
+ "maintitle",
117
+ "eventtitle"
118
+ ],
119
+ verbatim: [
120
+ "doi",
121
+ "eprint",
122
+ "file",
123
+ "files",
124
+ "pdf",
125
+ "groups",
126
+ // jabref unilaterally decided to make this non-standard field verbatim
127
+ "ids",
128
+ "url",
129
+ "verba",
130
+ "verbb",
131
+ "verbc",
132
+ /^keywords([+]duplicate-\d+)?$/,
133
+ /^citeulike-linkout-[0-9]+$/,
134
+ /^bdsk-url-[0-9]+$/
135
+ ],
136
+ richtext: [
137
+ "annotation",
138
+ "comment",
139
+ "annote",
140
+ "review",
141
+ "notes",
142
+ "note"
143
+ ],
144
+ literallist: [
145
+ "institution",
146
+ "publisher",
147
+ "origpublisher",
148
+ "organization",
149
+ "location",
150
+ "origlocation"
151
+ ]
152
+ };
153
+ const English = [
154
+ "",
155
+ "american",
156
+ "british",
157
+ "canadian",
158
+ "english",
159
+ "australian",
160
+ "newzealand",
161
+ "usenglish",
162
+ "ukenglish",
163
+ "en",
164
+ "eng",
165
+ "en-au",
166
+ "en-bz",
167
+ "en-ca",
168
+ "en-cb",
169
+ "en-gb",
170
+ "en-ie",
171
+ "en-jm",
172
+ "en-nz",
173
+ "en-ph",
174
+ "en-tt",
175
+ "en-us",
176
+ "en-za",
177
+ "en-zw",
178
+ "anglais"
179
+ // don't do this people
180
+ ];
181
+ const FieldAction = {
182
+ removeOuterBraces: [
183
+ "doi"
184
+ // 'publisher',
185
+ // 'location',
186
+ ],
187
+ parseInt: [
188
+ "year",
189
+ "month"
190
+ ],
191
+ noCrossRef: [
192
+ "file"
193
+ ]
194
+ };
195
+ const narguments = {
196
+ advance: 1,
197
+ ElsevierGlyph: 1,
198
+ bar: 1,
199
+ bibcyr: 1,
200
+ bibstring: 1,
201
+ chsf: 1,
202
+ cite: 1,
203
+ citeauthor: 1,
204
+ cyrchar: 1,
205
+ ding: 1,
206
+ emph: 1,
207
+ enquote: 1,
208
+ frac: 2,
209
+ hbox: 1,
210
+ href: 2,
211
+ hskip: 1,
212
+ hspace: 1,
213
+ ht: 1,
214
+ mathrm: 1,
215
+ mbox: 1,
216
+ mkbibbold: 1,
217
+ mkbibemph: 1,
218
+ mkbibitalic: 1,
219
+ mkbibquote: 1,
220
+ newcommand: 2,
221
+ noopsort: 1,
222
+ ocirc: 1,
223
+ overline: 1,
224
+ ProvideTextCommandDefault: 2,
225
+ rlap: 1,
226
+ sb: 1,
227
+ section: 1,
228
+ sp: 1,
229
+ subsection: 1,
230
+ subsubsection: 1,
231
+ subsubsubsection: 1,
232
+ t: 1,
233
+ textbf: 1,
234
+ textcite: 1,
235
+ textit: 1,
236
+ textrm: 1,
237
+ textsc: 1,
238
+ textsl: 1,
239
+ textsubscript: 1,
240
+ textsuperscript: 1,
241
+ texttt: 1,
242
+ textup: 1,
243
+ url: 1,
244
+ vphantom: 1,
245
+ vspace: 1,
246
+ wd: 1,
247
+ // math
248
+ "math _": 1,
249
+ "math ^": 1
250
+ };
251
+ for (const m in import_unicode2latex.combining.tounicode) {
252
+ narguments[m] = 1;
253
+ }
254
+ class BibTeXParser {
255
+ fallback;
256
+ current;
257
+ english;
258
+ options;
259
+ fieldMode;
260
+ newcommands = {};
261
+ bib;
262
+ unhandled = /* @__PURE__ */ new Set();
263
+ split(ast, sep, split) {
264
+ const roots = [];
265
+ const nodes = [...ast.content];
266
+ const types = nodes.map((node) => {
267
+ if (node.type === "whitespace") return " ";
268
+ if (node.type === "string" && node.content.match(sep)) return "&";
269
+ return ".";
270
+ }).join("");
271
+ types.split(split).forEach((match, i) => {
272
+ const content = match.length ? nodes.splice(0, match.length) : [];
273
+ if (i % 2 === 0) roots.push({ type: "root", content });
274
+ });
275
+ return roots;
276
+ }
277
+ trimCreator(cr) {
278
+ return JSON.parse(JSON.stringify(cr, (k, v) => typeof v === "string" ? v.trim() || void 0 : v));
279
+ }
280
+ parseCreator(ast) {
281
+ if (ast.content.length === 1 && ast.content[0].type === "group") return this.trimCreator({ name: this.stringify(ast, { mode: "creatorlist" }) });
282
+ const { parts, extended } = this.commaSeparatedCreator(ast);
283
+ if (extended) {
284
+ const name = {};
285
+ for (const [attr, value] of Object.entries(extended)) {
286
+ const rendered = this.stringify(value, { mode: "creatorlist" }).trim();
287
+ switch (attr) {
288
+ case "":
289
+ break;
290
+ case "given":
291
+ name.firstName = rendered;
292
+ break;
293
+ case "family":
294
+ name.lastName = rendered;
295
+ break;
296
+ case "given-i":
297
+ name.initial = rendered;
298
+ break;
299
+ case "useprefix":
300
+ case "juniorcomma":
301
+ name[attr] = rendered.toLowerCase() === "true";
302
+ break;
303
+ default:
304
+ name[attr] = rendered;
305
+ break;
306
+ }
307
+ }
308
+ return this.trimCreator(name);
309
+ } else if (parts.length) {
310
+ const nameparts = parts.map((part) => this.stringify(part, { mode: "creatorlist" }).trim());
311
+ if (nameparts.length === 3 && nameparts[2] === "") nameparts.pop();
312
+ if (nameparts.length > 3) {
313
+ const key = this.current.key ? `@${this.current.key}: ` : "";
314
+ this.bib.errors.push({
315
+ error: `${key}unexpected ${nameparts.length}-part name "${nameparts.join(", ")}", dropping "${nameparts.slice(3).join(", ")}"`,
316
+ input: nameparts.join(", ")
317
+ });
318
+ }
319
+ let [lastName, suffix, firstName] = nameparts.length === 2 ? [nameparts[0], void 0, nameparts[1]] : nameparts.slice(0, 3);
320
+ let prefix;
321
+ const m = lastName.match(/^([a-z'. ]+) (.+)/);
322
+ if (m) {
323
+ prefix = m[1];
324
+ lastName = m[2];
325
+ }
326
+ return this.trimCreator({
327
+ lastName,
328
+ firstName,
329
+ prefix,
330
+ suffix
331
+ });
332
+ } else {
333
+ const nameparts = this.split(ast, /^$/, /( )/).map((part) => this.stringify(part, { mode: "creatorlist" })).filter((n) => n);
334
+ if (nameparts.length === 1) return this.trimCreator({ lastName: nameparts[0] });
335
+ const prefix = nameparts.findIndex((n) => n.match(/^[a-z]/));
336
+ const postfix = prefix <= 0 ? -1 : nameparts.findIndex((n, i) => i > prefix && !n.match(/^[a-z]/));
337
+ if (postfix === -1) {
338
+ const lastName = nameparts.pop();
339
+ return this.trimCreator({ lastName, firstName: nameparts.join(" ") });
340
+ }
341
+ return this.trimCreator({
342
+ firstName: nameparts.slice(0, prefix).join(" "),
343
+ prefix: nameparts.slice(prefix, postfix).join(" "),
344
+ lastName: nameparts.slice(postfix).join(" ")
345
+ });
346
+ }
347
+ }
348
+ ligature(nodes) {
349
+ if (latexMode(nodes[0]) !== "text") return null;
350
+ const max = 3;
351
+ const slice = nodes.slice(0, max);
352
+ const type = slice.map((n) => n.type === "string" ? "s" : " ").join("");
353
+ if (type[0] !== "s") return null;
354
+ const content = slice.map((n) => n.type === "string" ? n.content : "");
355
+ let latex;
356
+ while (content.length) {
357
+ if (type.startsWith("s".repeat(content.length)) && (latex = latex2unicode(content.join(""), slice[0]))) {
358
+ try {
359
+ return { type: "string", content: latex, _renderInfo: {} };
360
+ } finally {
361
+ nodes.splice(0, content.length);
362
+ }
363
+ }
364
+ content.pop();
365
+ }
366
+ return null;
367
+ }
368
+ wraparg(node, macro) {
369
+ if (macro.content.match(/^(itshape|textsl|textit|emph|mkbibemph)$/)) node._renderInfo.emph = true;
370
+ if (macro.content.match(/^(textbf|mkbibbold|bfseries)$/)) node._renderInfo.bold = true;
371
+ if (macro.content.match(/^(textsc)$/)) node._renderInfo.smallCaps = true;
372
+ if (macro.content.match(/^(texttt)$/)) node._renderInfo.code = true;
373
+ return { type: "argument", content: [node], openMark: "", closeMark: "", _renderInfo: { mode: node._renderInfo.mode } };
374
+ }
375
+ argtogroup(node) {
376
+ if (node.content.length === 1 && node.content[0].type === "group") return node.content[0];
377
+ return { type: "group", content: node.content };
378
+ }
379
+ argument(nodes, macro) {
380
+ if (!nodes.length) return null;
381
+ if (nodes[0].type === "whitespace") nodes.shift();
382
+ if (!nodes.length) return null;
383
+ if (nodes[0].type === "string") {
384
+ const char = nodes[0].content[0];
385
+ nodes[0].content = nodes[0].content.substr(1);
386
+ const arg = { ...nodes[0], content: char };
387
+ if (!nodes[0].content) nodes.shift();
388
+ return this.wraparg(arg, macro);
389
+ }
390
+ return this.wraparg(nodes.shift(), macro);
391
+ }
392
+ unsupported(node) {
393
+ const tex = (0, import_unified_latex_util_print_raw.printRaw)(node);
394
+ if (this.fallback) return this.fallback(node, tex, this.current) ?? "";
395
+ let id;
396
+ switch (node.type) {
397
+ case "macro":
398
+ id = `${node.type}.${node.content}`;
399
+ if (!this.unhandled.has(id)) {
400
+ this.unhandled.add(id);
401
+ this.bib.errors.push({ error: `unhandled ${node.type} ${(0, import_unified_latex_util_print_raw.printRaw)(node)}`, input: (0, import_unified_latex_util_print_raw.printRaw)(node) });
402
+ }
403
+ break;
404
+ case "environment":
405
+ id = `${node.type}.${node.env}`;
406
+ if (!this.unhandled.has(id)) {
407
+ this.unhandled.add(id);
408
+ this.bib.errors.push({ error: `unhandled ${node.type} ${node.env} (${(0, import_unified_latex_util_print_raw.printRaw)(node)})`, input: (0, import_unified_latex_util_print_raw.printRaw)(node) });
409
+ }
410
+ break;
411
+ default:
412
+ this.bib.errors.push({ error: `unhandled ${node.type} (${(0, import_unified_latex_util_print_raw.printRaw)(node)})`, input: (0, import_unified_latex_util_print_raw.printRaw)(node) });
413
+ break;
414
+ }
415
+ return tex;
416
+ }
417
+ wrap(text, tag, wrap = true) {
418
+ if (!text || !wrap) return text || "";
419
+ return `${tag}${text}/${tag}`;
420
+ }
421
+ registercommand(node) {
422
+ const types = (nodes) => nodes.map((n) => n.type).join(".");
423
+ const group = (arg, kind) => {
424
+ if (!arg) throw new Error(`missing ${kind} for ${(0, import_unified_latex_util_print_raw.printRaw)(node)} @ ${JSON.stringify(node.position)}`);
425
+ if (types(arg.content) !== "group") throw new Error(`Malformed ${kind} for ${(0, import_unified_latex_util_print_raw.printRaw)(node)} @ ${JSON.stringify(node.position)}`);
426
+ return arg.content[0].content;
427
+ };
428
+ if (!node.args) throw new Error(`No arguments for ${(0, import_unified_latex_util_print_raw.printRaw)(node)} @ ${JSON.stringify(node.position)}`);
429
+ const namearg = group(node.args[0], "name");
430
+ if (types(namearg) !== "macro") throw new Error(`Unexpected name for ${(0, import_unified_latex_util_print_raw.printRaw)(node)} @ ${JSON.stringify(node.position)}`);
431
+ this.newcommands[namearg[0].content] = node.args[1];
432
+ return "";
433
+ }
434
+ subp(text, mode) {
435
+ const macro = { sub: "_", sup: "^" }[mode];
436
+ let subp = "";
437
+ for (let char of text) {
438
+ const mapped = import_unicode2latex.latex2unicode[`${macro}{${char}}`];
439
+ switch (typeof mapped) {
440
+ case "string":
441
+ subp += mapped;
442
+ break;
443
+ case "undefined":
444
+ return `${mode}${text}/${mode}`;
445
+ default:
446
+ subp += mapped.math;
447
+ }
448
+ }
449
+ return subp;
450
+ }
451
+ macro(node, context) {
452
+ var _a, _b, _c, _d, _e, _f, _g;
453
+ const text = latex2unicode((0, import_unified_latex_util_print_raw.printRaw)(node), node);
454
+ if (text) return text;
455
+ let url;
456
+ let label;
457
+ let arg;
458
+ switch (node.content) {
459
+ case "newcommand":
460
+ case "ProvideTextCommandDefault":
461
+ return this.registercommand(node);
462
+ // too complex to deal with these
463
+ case "raise":
464
+ case "accent":
465
+ case "def":
466
+ case "hss":
467
+ case "ifmmode":
468
+ case "makeatletter":
469
+ case "makeatother":
470
+ case "scriptscriptstyle":
471
+ case "setbox":
472
+ case "dimen":
473
+ case "advance":
474
+ return "";
475
+ case "vphantom":
476
+ case "noopsort":
477
+ case "left":
478
+ case "right":
479
+ case "ensuremath":
480
+ case "wd":
481
+ case "ht":
482
+ return "";
483
+ case "path":
484
+ return "";
485
+ // until https://github.com/siefkenj/unified-latex/issues/94 is fixed
486
+ case "hspace":
487
+ case "hskip":
488
+ if (node.args && node.args.length) {
489
+ if ((0, import_unified_latex_util_print_raw.printRaw)(node.args).match(/^[{]?0[a-z]*$/)) return "";
490
+ return " ";
491
+ }
492
+ return "";
493
+ case "overline":
494
+ case "bar":
495
+ return node.args.map((a) => this.stringify(a, context)).join("").replace(/[a-z0-9]/ig, (m) => `${m}\u0305`);
496
+ // accents dealt with by preprocessor
497
+ case "textup":
498
+ case "textsc":
499
+ case "textrm":
500
+ case "texttt":
501
+ case "mathrm":
502
+ case "mbox":
503
+ case "hbox":
504
+ case "rlap":
505
+ return node.args.map((n) => this.stringify(n, context)).join("");
506
+ case "href":
507
+ case "url":
508
+ if (node.args) {
509
+ url = node.args[0];
510
+ label = node.args[node.content === "url" ? 0 : 1];
511
+ }
512
+ return `<a href="${this.stringify(url, context)}">${this.stringify(label, context)}</a>`;
513
+ case "relax":
514
+ case "aftergroup":
515
+ case "ignorespaces":
516
+ case "em":
517
+ case "it":
518
+ case "tt":
519
+ case "sl":
520
+ return "";
521
+ case "rm":
522
+ case "sc":
523
+ return "";
524
+ // bold/emph/smallcaps is handled in the wrapper
525
+ case "textbf":
526
+ case "mkbibbold":
527
+ case "textit":
528
+ case "emph":
529
+ case "mkbibemph":
530
+ return this.stringify((_a = node.args) == null ? void 0 : _a[0], context);
531
+ case "textsuperscript":
532
+ return this.subp(this.stringify((_b = node.args) == null ? void 0 : _b[0], context), "sup");
533
+ case "textsubscript":
534
+ return this.subp(this.stringify((_c = node.args) == null ? void 0 : _c[0], context), "sub");
535
+ case "_":
536
+ case "^":
537
+ switch (latexMode(node)) {
538
+ case "math":
539
+ return this.subp(this.stringify((_d = node.args) == null ? void 0 : _d[0], context), node.content === "^" ? "sup" : "sub");
540
+ default:
541
+ return node.content;
542
+ }
543
+ case "LaTeX":
544
+ return this.wrap(`L${this.subp("A", "sup")}T${this.subp("E", "sub")}X`, "ncx");
545
+ case "enquote":
546
+ case "mkbibquote":
547
+ return this.wrap(this.stringify((_e = node.args) == null ? void 0 : _e[0], context), "enquote");
548
+ case "\\":
549
+ return context.mode === "richtext" ? open.br : " ";
550
+ case "par":
551
+ return context.mode === "richtext" ? open.p : " ";
552
+ case "item":
553
+ return context.mode === "richtext" ? open.li : " ";
554
+ case "section":
555
+ case "subsection":
556
+ case "subsubsection":
557
+ case "subsubsubsection":
558
+ return this.wrap(this.stringify((_f = node.args) == null ? void 0 : _f[0], context), `h${node.content.split("sub").length}`);
559
+ case "frac":
560
+ arg = node.args.map((a) => this.stringify(a, context));
561
+ if (arg.length === 2) {
562
+ const resolved = import_unicode2latex.latex2unicode[`\\frac${arg.map((a) => `{${a}}`).join("")}`];
563
+ if (resolved) return typeof resolved === "string" ? resolved : resolved.math || resolved.text;
564
+ }
565
+ return arg.map((part, i) => this.subp(part, i ? "sub" : "sup")).join("\u2044");
566
+ case "chsf":
567
+ case "bibstring":
568
+ case "cite":
569
+ case "textcite":
570
+ case "citeauthor":
571
+ return this.wrap(this.stringify((_g = node.args) == null ? void 0 : _g[0], context), "ncx", context.mode === "title");
572
+ default:
573
+ if (this.newcommands[node.content]) return this.stringify(this.newcommands[node.content], context);
574
+ return this.unsupported(node);
575
+ }
576
+ }
577
+ what(node) {
578
+ if (!node) return "";
579
+ switch (node.type) {
580
+ case "macro":
581
+ return `macro:${node._renderInfo.mode ?? "text"}:${node.content}`;
582
+ case "environment":
583
+ return `env:${node.env}`;
584
+ default:
585
+ return node.type;
586
+ }
587
+ }
588
+ environment(node, context) {
589
+ while (node.content.length && this.what(node.content[0]).match(/^parbreak|whitespace|macro:text:par$/)) node.content.shift();
590
+ while (node.content.length && this.what(node.content[node.content.length - 1]).match(/^parbreak|whitespace|macro:text:par$/)) node.content.pop();
591
+ switch (node.env) {
592
+ case "quotation":
593
+ return this.wrap(node.content.map((n) => this.stringify(n, context)).join(""), "blockquote", context.mode === "richtext");
594
+ case "itemize":
595
+ return this.wrap(node.content.map((n) => this.stringify(n, context)).join(""), "ul", context.mode === "richtext");
596
+ case "em":
597
+ return this.wrap(node.content.map((n) => this.stringify(n, context)).join(""), "i", context.mode === "richtext");
598
+ default:
599
+ return this.unsupported(node);
600
+ }
601
+ }
602
+ stringify(node, context) {
603
+ let content = this.stringifyContent(node, context);
604
+ if (content && node._renderInfo) {
605
+ if (node._renderInfo.emph) content = `${open.i}${content}${close.i}`;
606
+ if (node._renderInfo.bold) content = `${open.b}${content}${close.b}`;
607
+ if (node._renderInfo.smallCaps) content = `${open.sc}${content}${close.sc}`;
608
+ if (node._renderInfo.code) content = `${open.code}${content}${close.code}`;
609
+ if (this.english && node._renderInfo.protectCase) content = `${open.nc}${content}${close.nc}`;
610
+ }
611
+ return content;
612
+ }
613
+ stringifyContent(node, context) {
614
+ if (!node) return "";
615
+ switch (node.type) {
616
+ case "root":
617
+ case "argument":
618
+ case "group":
619
+ case "inlinemath":
620
+ return node.content.map((n) => this.stringify(n, context)).join("");
621
+ case "string":
622
+ case "verbatim":
623
+ return node.content;
624
+ case "macro":
625
+ return this.macro(node, context);
626
+ case "parbreak":
627
+ return context.mode === "richtext" ? open.p : " ";
628
+ case "whitespace":
629
+ return node._renderInfo.mode === "math" ? "" : " ";
630
+ case "comment":
631
+ return "";
632
+ case "environment":
633
+ return this.environment(node, context);
634
+ case "verb":
635
+ return node.content;
636
+ default:
637
+ return this.unsupported(node);
638
+ }
639
+ }
640
+ protect(node) {
641
+ if (node.type === "inlinemath") return true;
642
+ if (node.type !== "group") return false;
643
+ if (!node.content.length) return false;
644
+ return node.content[0].type !== "macro";
645
+ }
646
+ mode(field) {
647
+ if (this.options.verbatimFields && this.options.verbatimFields.find((name) => typeof name === "string" ? name === field : field.match(name))) return "verbatim";
648
+ let mode = "literal";
649
+ for (const [selected, fields] of Object.entries(this.fieldMode)) {
650
+ if (fields.find((match) => typeof match === "string" ? field === match : field.match(match))) mode = selected;
651
+ }
652
+ return mode;
653
+ }
654
+ restoreMarkup(s) {
655
+ if (!s.includes("")) return s;
656
+ const restored = [s.replace(/\x0E\/?ncx\x0F/ig, "")];
657
+ while (restored[0] !== restored[1]) {
658
+ restored.unshift(restored[0].replace(collapsable, "$2"));
659
+ }
660
+ return restored[0].replace(/(\x0Ep\x0F\s*){2,}/ig, "p").replace(/\s*(\x0E\/p\x0F){2,}/ig, "/p").replace(/\x0Eenquote\x0F/ig, "\u201C").replace(/\x0E\/enquote\x0F/ig, "\u201D").replace(/\x0Esc\x0F/ig, '<span style="font-variant:small-caps;">').replace(/\x0E\/sc\x0F/ig, "</span>").replace(/\x0Enc\x0F/ig, '<span class="nocase">').replace(/\x0E\/nc\x0F/ig, "</span>").replace(/\x0E/ig, "<").replace(/\x0F/ig, ">");
661
+ }
662
+ stringField(field, value, mode, guessSC) {
663
+ if (field === "crossref") return value;
664
+ if (FieldAction.parseInt.includes(field) && value.trim().match(/^-?\d+$/)) return `${parseInt(value)}`;
665
+ if (this.english && mode === "title") {
666
+ value = (0, import_sentence_case.toSentenceCase)(value, {
667
+ preserveQuoted: this.options.sentenceCase && this.options.sentenceCase.preserveQuoted,
668
+ subSentenceCapitalization: this.options.sentenceCase && this.options.sentenceCase.subSentence,
669
+ markup: /\x0E\/?([a-z]+)\x0F/ig,
670
+ nocase: /\x0E(ncx?)\x0F.*?\x0E\/\1\x0F/ig,
671
+ guess: guessSC
672
+ });
673
+ let cancel = (_match, stripped) => stripped;
674
+ switch (this.options.caseProtection) {
675
+ case "strict":
676
+ cancel = (match, _stripped) => match;
677
+ break;
678
+ case "as-needed":
679
+ cancel = (match, stripped) => {
680
+ const words = (0, import_tokenizer.tokenize)(stripped, /\x0E\/?([a-z]+)\x0F/ig);
681
+ return words.find((w) => w.shape.match(/^(?!.*X).*x.*$/)) ? match : this.wrap(stripped, "ncx");
682
+ };
683
+ break;
684
+ }
685
+ return value.replace(/\x0Enc\x0F(.*?)\x0E\/nc\x0F/ig, cancel);
686
+ }
687
+ return value;
688
+ }
689
+ commaSeparatedCreator(ast) {
690
+ var _a;
691
+ const result = {
692
+ parts: []
693
+ };
694
+ if (!ast.content.find((node) => node.type === "string" && node.content === ",")) return result;
695
+ result.parts = this.split(ast, /^,$/, /(&)/);
696
+ result.extended = {};
697
+ for (const part of result.parts) {
698
+ const start = ((_a = part.content[0]) == null ? void 0 : _a.type) === "whitespace" ? 1 : 0;
699
+ let signature = part.content.slice(start, start + 4).map((node, i) => node._renderInfo.mode === "text" && node.type === "string" ? node.content.replace(i % 2 ? /[^=-]/g : /[^a-z]/gi, ".") : ".").join("");
700
+ if (signature.match(/^[a-z]+(-[a-z]+)?=/i)) {
701
+ signature = signature.replace(/=.*/, "").toLowerCase();
702
+ result.extended[signature] = { type: "root", content: part.content.slice(signature.includes("-") ? start + 4 : start + 2) };
703
+ } else {
704
+ delete result.extended;
705
+ break;
706
+ }
707
+ }
708
+ return result;
709
+ }
710
+ field(entry, field, value) {
711
+ const mode = entry.mode[field] = this.mode(field);
712
+ const caseProtection = {
713
+ present: false,
714
+ intuitive: 0
715
+ // a lot of people don't realise `some text \textit{in italics}` will protect 'in italics'
716
+ };
717
+ const ast = import_unified_latex_util_pegjs.LatexPegParser.parse(value);
718
+ if (this.options.removeOuterBraces.includes(field) && ast.content.length === 1 && ast.content[0].type === "group") {
719
+ ast.content = ast.content[0].content;
720
+ }
721
+ if (mode === "verbatim") {
722
+ entry.fields[field] = (0, import_unified_latex_util_print_raw.printRaw)(ast);
723
+ return;
724
+ }
725
+ if (this.english && mode === "title") {
726
+ let root = [...ast.content];
727
+ while (root.length) {
728
+ const node = root.shift();
729
+ if (this.protect(node)) node._renderInfo = { root: true };
730
+ if (node.type === "environment") root = [...root, ...node.content];
731
+ }
732
+ }
733
+ (0, import_unified_latex_util_visit.visit)(ast, (node, info) => {
734
+ if (!node._renderInfo) node._renderInfo = {};
735
+ node._renderInfo.mode = info.context.inMathMode ? "math" : "text";
736
+ if (mode === "title" && node.type === "inlinemath" && !info.parents.find((p) => p._renderInfo.protectCase)) node._renderInfo.protectCase = true;
737
+ if (!info.context.inMathMode) {
738
+ if (mode === "title" && node._renderInfo.root && (node.type !== "group" || node.content[0].type !== "macro")) {
739
+ node._renderInfo.protectCase = true;
740
+ if (node.type === "group") {
741
+ caseProtection.present = true;
742
+ caseProtection.intuitive += 1;
743
+ }
744
+ }
745
+ if (node.type === "macro" && typeof node.escapeToken !== "string") node.escapeToken = "\\";
746
+ if (node.type === "environment" && node.env === "em") node._renderInfo.emph = true;
747
+ }
748
+ });
749
+ if (this.options.raw) {
750
+ switch (mode) {
751
+ case "creatorlist":
752
+ entry.fields[field] = this.split(ast, /^and$/i, /(^& | & | &$)/).map((cr) => {
753
+ const { parts, extended } = this.commaSeparatedCreator(cr);
754
+ if (parts.length === 2 && !extended) {
755
+ return this.trimCreator({ lastName: (0, import_unified_latex_util_print_raw.printRaw)(parts[0]), firstName: (0, import_unified_latex_util_print_raw.printRaw)(parts[1]) });
756
+ }
757
+ if (!parts.length) {
758
+ const nameparts = this.split(ast, /^$/, /( )/);
759
+ if (nameparts.length === 2) {
760
+ return this.trimCreator({
761
+ lastName: (0, import_unified_latex_util_print_raw.printRaw)(nameparts[1]),
762
+ firstName: (0, import_unified_latex_util_print_raw.printRaw)(nameparts[0])
763
+ });
764
+ }
765
+ }
766
+ return { name: (0, import_unified_latex_util_print_raw.printRaw)(cr) };
767
+ });
768
+ return;
769
+ case "literallist":
770
+ entry.fields[field] = this.split(ast, /^and$/i, /(^& | & | &$)/).map((elt) => (0, import_unified_latex_util_print_raw.printRaw)(elt));
771
+ return;
772
+ default:
773
+ entry.fields[field] = (0, import_unified_latex_util_print_raw.printRaw)(ast);
774
+ return;
775
+ }
776
+ }
777
+ (0, import_unified_latex_util_visit.visit)(ast, (nodes, info) => {
778
+ var _a;
779
+ let node;
780
+ const compacted = [];
781
+ let inif = 0;
782
+ while (nodes.length) {
783
+ if (node = this.ligature(nodes)) {
784
+ compacted.push(node);
785
+ continue;
786
+ }
787
+ node = nodes.shift();
788
+ if (node.type === "macro" && node.content === "ifdefined") {
789
+ inif += 1;
790
+ continue;
791
+ } else if (node.type === "macro" && node.content === "else") {
792
+ continue;
793
+ } else if (node.type === "macro" && node.content === "fi") {
794
+ inif = Math.max(inif - 1, 0);
795
+ continue;
796
+ } else if (inif) {
797
+ continue;
798
+ }
799
+ const nargs = node.type === "macro" ? narguments[node.content] || narguments[`${info.context.inMathMode ? "math" : "text"} ${node.content}`] : 0;
800
+ if (node.type === "macro" && nargs) {
801
+ node.args = Array(nargs).fill(void 0).map((_i) => this.argument(nodes, node)).filter((arg) => arg);
802
+ if (node.content.match(/^(url|href)$/) && node.args.length) {
803
+ let url = node.args[0].content;
804
+ if (url.length === 1 && url[0].type === "group") url = url[0].content;
805
+ node.args[0] = this.wraparg({ type: "string", content: (0, import_unified_latex_util_print_raw.printRaw)(url), _renderInfo: { mode: url[0]._renderInfo.mode } }, node);
806
+ }
807
+ caseProtection.intuitive -= node.args.filter((arg) => arg.content[0].type === "group" && arg.content[0]._renderInfo.protectCase).length;
808
+ } else if (node.type === "macro" && node.content.match(/^[a-z]+$/i) && ((_a = nodes[0]) == null ? void 0 : _a.type) === "whitespace") {
809
+ nodes.shift();
810
+ }
811
+ compacted.push(node);
812
+ }
813
+ if (!info.context.inMathMode) {
814
+ for (const [macro, markup] of Object.entries({ em: "emph", it: "emph", sl: "emph", bf: "bold", sc: "smallCaps", tt: "code" })) {
815
+ if (info.parents.find((p) => p._renderInfo[markup])) continue;
816
+ compacted.forEach((markup_node, i) => {
817
+ if (markup_node.type === "macro" && markup_node.content === macro) {
818
+ compacted.slice(i + 1).forEach((n) => n._renderInfo[markup] = true);
819
+ }
820
+ });
821
+ }
822
+ }
823
+ nodes.push(...compacted);
824
+ }, { test: Array.isArray, includeArrays: true });
825
+ (0, import_unified_latex_util_replace.replaceNode)(ast, (node, _info) => {
826
+ if (node.type !== "macro") return;
827
+ if (node.escapeToken && import_unicode2latex.combining.tounicode[node.content]) {
828
+ let arg;
829
+ if (!node.args || node.args.length === 0 || node.args[0].content.length === 0) {
830
+ arg = { type: "string", content: " ", _renderInfo: {} };
831
+ } else if (node.args.length !== 1 || node.args[0].content.length !== 1) {
832
+ return;
833
+ } else {
834
+ arg = node.args[0].content[0];
835
+ }
836
+ if (arg.type === "group") {
837
+ switch (arg.content.length) {
838
+ case 0:
839
+ arg = { type: "string", content: " ", _renderInfo: {} };
840
+ break;
841
+ case 1:
842
+ arg = arg.content[0];
843
+ break;
844
+ default:
845
+ return;
846
+ }
847
+ }
848
+ switch (arg.type) {
849
+ case "verbatim":
850
+ case "string":
851
+ return { type: "string", content: `${arg.content}${import_unicode2latex.combining.tounicode[node.content]}`, _renderInfo: {} };
852
+ default:
853
+ return;
854
+ }
855
+ }
856
+ let latex = `${node.escapeToken}${node.content}`;
857
+ latex += (node.args || []).map((arg) => (0, import_unified_latex_util_print_raw.printRaw)(this.argtogroup(arg))).join("");
858
+ if (latex in import_unicode2latex.latex2unicode) return { type: "string", content: latex2unicode(latex, node), _renderInfo: {} };
859
+ });
860
+ switch (mode) {
861
+ case "creatorlist":
862
+ entry.fields[field] = this.split(ast, /^and$/i, /(^& | & | &$)/).map((cr) => this.parseCreator(cr)).filter((cr) => Object.keys(cr).length);
863
+ break;
864
+ case "literallist":
865
+ entry.fields[field] = this.split(ast, /^and$/i, /(^& | & | &$)/).map((elt) => this.stringify(elt, { mode: "literal" }).trim());
866
+ break;
867
+ default:
868
+ entry.fields[field] = this.stringField(
869
+ field,
870
+ this.stringify(ast, { mode }),
871
+ mode,
872
+ this.options.sentenceCase && this.options.sentenceCase.guess
873
+ // && (!caseProtection.present || caseProtection.intuitive > 0)
874
+ );
875
+ break;
876
+ }
877
+ entry.fields[field] = JSON.parse(JSON.stringify(entry.fields[field], (k, v) => typeof v === "string" ? this.restoreMarkup(v) : v));
878
+ }
879
+ reset(options = {}) {
880
+ if (options.sentenceCase === false) {
881
+ options = {
882
+ ...options,
883
+ english: false,
884
+ sentenceCase: {
885
+ guess: false,
886
+ subSentence: false,
887
+ preserveQuoted: false
888
+ }
889
+ };
890
+ }
891
+ this.options = (0, import_merge.merge)(options, {
892
+ caseProtection: "as-needed",
893
+ applyCrossRef: options.applyCrossRef ?? true,
894
+ fieldMode: {},
895
+ english: English,
896
+ sentenceCase: {
897
+ guess: true,
898
+ preserveQuoted: true
899
+ }
900
+ });
901
+ if (this.options.caseProtection === true) this.options.caseProtection = "as-needed";
902
+ if (this.options.verbatimFields) this.options.verbatimFields = this.options.verbatimFields.map((f) => typeof f === "string" ? f.toLowerCase() : new RegExp(f.source, f.flags + (f.flags.includes("i") ? "" : "i")));
903
+ if (typeof this.options.english === "boolean") this.options.english = this.options.english ? English : [];
904
+ this.options.english = this.options.english.map((langid) => langid.toLowerCase());
905
+ this.fieldMode = Object.entries(FieldMode).reduce((acc, [mode, test]) => {
906
+ const strings = test.filter((fieldname_or_regex) => typeof fieldname_or_regex === "string" && !this.options.fieldMode[fieldname_or_regex]);
907
+ const regexes = test.filter((fieldname_or_regex) => typeof fieldname_or_regex !== "string");
908
+ acc[mode] = [...strings, ...regexes];
909
+ return acc;
910
+ }, {});
911
+ for (const [field, mode] of Object.entries(this.options.fieldMode)) {
912
+ this.fieldMode[mode].unshift(field);
913
+ }
914
+ if (!this.options.removeOuterBraces) {
915
+ this.options.removeOuterBraces = [
916
+ ...FieldAction.removeOuterBraces,
917
+ ...this.fieldMode.title,
918
+ ...this.fieldMode.verbatim
919
+ ].filter((field) => typeof field === "string");
920
+ }
921
+ this.fallback = options.unsupported === "ignore" ? ((_node, _tex) => "") : options.unsupported;
922
+ this.bib = {
923
+ errors: [],
924
+ entries: [],
925
+ comments: [],
926
+ strings: {},
927
+ preamble: [],
928
+ jabref: null
929
+ };
930
+ }
931
+ reparse(verbatim) {
932
+ let langid = (verbatim.fields.langid || verbatim.fields.hyphenation || "").toLowerCase();
933
+ if (!langid && this.options.languageAsLangid && verbatim.fields.language) langid = verbatim.fields.language.toLowerCase();
934
+ this.english = this.options.english.includes(langid);
935
+ const entry = this.current = {
936
+ type: verbatim.type,
937
+ key: verbatim.key,
938
+ fields: {},
939
+ mode: {},
940
+ input: verbatim.input
941
+ };
942
+ let keywords = [];
943
+ try {
944
+ for (let [field, value] of Object.entries(verbatim.fields)) {
945
+ if (!value.trim()) continue;
946
+ if (field.match(/^keywords([+]duplicate-\d+)?$/)) field = "keywords";
947
+ this.field(entry, field, value);
948
+ if (field === "keywords") {
949
+ keywords = [...keywords, ...entry.fields.keywords.split(/\s*[,;]\s*/)].map((k) => k.trim()).filter((k) => k);
950
+ delete entry.fields.keywords;
951
+ }
952
+ if (!this.options.raw && typeof entry.fields[field] === "string") {
953
+ entry.fields[field] = entry.fields[field].trim();
954
+ if (field === "month") entry.fields[field] = Month[entry.fields[field].toLowerCase()] || entry.fields[field];
955
+ }
956
+ }
957
+ if (keywords.length) {
958
+ entry.fields.keywords = [...new Set(keywords)].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
959
+ entry.mode.keywords = "verbatimlist";
960
+ }
961
+ this.bib.entries.push(entry);
962
+ } catch (err) {
963
+ this.bib.errors.push({ error: `${err.message}
964
+ ${entry.input}`, input: entry.input });
965
+ }
966
+ }
967
+ content(tex) {
968
+ const entry = { key: "", type: "", fields: {}, mode: {}, input: tex };
969
+ const english = this.english;
970
+ this.english = false;
971
+ this.field(entry, "tex", tex);
972
+ this.english = english;
973
+ return entry.fields.tex;
974
+ }
975
+ prep(base) {
976
+ for (const preamble of base.preambles) {
977
+ try {
978
+ this.content(preamble);
979
+ } catch {
980
+ }
981
+ }
982
+ for (const [k, v] of Object.entries(base.strings)) {
983
+ this.bib.strings[k] = this.content(v);
984
+ }
985
+ }
986
+ finalize(base) {
987
+ var _a;
988
+ if (this.options.applyCrossRef) {
989
+ const entries = {};
990
+ for (const entry of this.bib.entries) {
991
+ if (entry.key) entries[entry.key.toUpperCase()] = entry;
992
+ }
993
+ const order = [];
994
+ for (const entry of this.bib.entries) {
995
+ if (!entry.key || typeof entry.fields.crossref !== "string") continue;
996
+ const crossref = entry.fields.crossref.toUpperCase();
997
+ if (!entries[crossref]) continue;
998
+ const key = entry.key.toUpperCase();
999
+ if (!order.includes(crossref)) order.unshift(crossref);
1000
+ if (!order.includes(key)) order.push(key);
1001
+ }
1002
+ const add = (obj, kind, field) => {
1003
+ obj[kind] = [.../* @__PURE__ */ new Set([...obj[kind], field])].sort();
1004
+ };
1005
+ for (const key of order) {
1006
+ const child = entries[key.toUpperCase()];
1007
+ const parent = entries[(_a = child.fields.crossref) == null ? void 0 : _a.toUpperCase()];
1008
+ if (!parent) continue;
1009
+ child.crossref = child.crossref || { donated: [], inherited: [] };
1010
+ parent.crossref = parent.crossref || { donated: [], inherited: [] };
1011
+ for (const mappings of [import_crossref.default[child.type], import_crossref.default["*"]].filter((m) => m)) {
1012
+ for (const mapping of [mappings[parent.type], mappings["*"]].filter((m) => m)) {
1013
+ for (const [childfield, parentfield] of Object.entries(mapping)) {
1014
+ if (!child.fields[childfield] && parent.fields[parentfield]) {
1015
+ child.fields[childfield] = parent.fields[parentfield];
1016
+ add(child.crossref, "inherited", childfield);
1017
+ add(parent.crossref, "donated", parentfield);
1018
+ }
1019
+ }
1020
+ for (const field of import_fields.default[child.type] || []) {
1021
+ if (FieldAction.noCrossRef.includes(field)) continue;
1022
+ if (!child.fields[field] && parent.fields[field]) {
1023
+ child.fields[field] = parent.fields[field];
1024
+ add(child.crossref, "inherited", field);
1025
+ add(parent.crossref, "donated", field);
1026
+ }
1027
+ }
1028
+ }
1029
+ }
1030
+ }
1031
+ for (const entry of this.bib.entries) {
1032
+ if (entry.crossref && !entry.crossref.donated.length && !entry.crossref.inherited.length) delete entry.crossref;
1033
+ }
1034
+ }
1035
+ const { comments, jabref } = JabRef.parse(base.comments);
1036
+ this.bib.comments = comments;
1037
+ this.bib.jabref = jabref;
1038
+ this.bib.preamble = base.preambles;
1039
+ this.bib.errors = [...base.errors, ...this.bib.errors];
1040
+ }
1041
+ parse(input, options = {}) {
1042
+ this.reset(options);
1043
+ const base = bibtex.parse(input, { strings: options.strings });
1044
+ this.prep(base);
1045
+ for (const entry of base.entries) {
1046
+ this.reparse(entry);
1047
+ }
1048
+ this.finalize(base);
1049
+ return this.bib;
1050
+ }
1051
+ async parseAsync(input, options = {}) {
1052
+ this.reset(options);
1053
+ const base = await bibtex.promises.parse(input, { strings: options.strings });
1054
+ this.prep(base);
1055
+ let n = 1;
1056
+ for (const entry of base.entries) {
1057
+ this.reparse(entry);
1058
+ if (n++ % 1e3 === 0) await (0, import_yield.playnice)();
1059
+ }
1060
+ this.finalize(base);
1061
+ return this.bib;
1062
+ }
1063
+ }
1064
+ function parse(input, options = {}) {
1065
+ const parser = new BibTeXParser();
1066
+ return parser.parse(input, options);
1067
+ }
1068
+ async function parseAsync(input, options = {}) {
1069
+ const parser = new BibTeXParser();
1070
+ return await parser.parseAsync(input, options);
1071
+ }
1072
+ //# sourceMappingURL=index.js.map