@unified-latex/unified-latex-util-catcode 1.6.0 → 1.7.0

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.cjs CHANGED
@@ -1,36 +1,7 @@
1
1
  "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // index.ts
21
- var unified_latex_util_catcode_exports = {};
22
- __export(unified_latex_util_catcode_exports, {
23
- findExpl3AndAtLetterRegionsInArray: () => findExpl3AndAtLetterRegionsInArray,
24
- findRegionInArray: () => findRegionInArray,
25
- hasReparsableMacroNames: () => hasReparsableMacroNames,
26
- hasReparsableMacroNamesInArray: () => hasReparsableMacroNamesInArray,
27
- reparseExpl3AndAtLetterRegions: () => reparseExpl3AndAtLetterRegions,
28
- reparseMacroNames: () => reparseMacroNames,
29
- reparseMacroNamesInArray: () => reparseMacroNamesInArray
30
- });
31
- module.exports = __toCommonJS(unified_latex_util_catcode_exports);
32
-
33
- // libs/find-region.ts
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const unifiedLatexUtilMatch = require("@unified-latex/unified-latex-util-match");
4
+ const unifiedLatexUtilVisit = require("@unified-latex/unified-latex-util-visit");
34
5
  function findRegionInArray(tree, start, end) {
35
6
  const ret = [];
36
7
  let currRegion = { start: void 0, end: tree.length };
@@ -50,249 +21,6 @@ function findRegionInArray(tree, start, end) {
50
21
  }
51
22
  return ret;
52
23
  }
53
-
54
- // ../unified-latex-util-print-raw/dist/index.js
55
- var linebreak = Symbol("linebreak");
56
- var ESCAPE = "\\";
57
- function _printRaw(node) {
58
- if (typeof node === "string") {
59
- return [node];
60
- }
61
- if (Array.isArray(node)) {
62
- return [].concat(
63
- ...node.map((n) => _printRaw(n))
64
- );
65
- }
66
- let argsString, escape;
67
- switch (node.type) {
68
- case "root":
69
- return _printRaw(node.content);
70
- case "argument":
71
- return [node.openMark, ..._printRaw(node.content), node.closeMark];
72
- case "comment":
73
- let suffix = node.suffixParbreak ? "" : linebreak;
74
- let leadingWhitespace = "";
75
- if (node.sameline && node.leadingWhitespace) {
76
- leadingWhitespace = " ";
77
- }
78
- if (node.sameline) {
79
- return [
80
- leadingWhitespace,
81
- "%",
82
- ..._printRaw(node.content),
83
- suffix
84
- ];
85
- }
86
- return [linebreak, "%", ..._printRaw(node.content), suffix];
87
- case "environment":
88
- case "mathenv":
89
- case "verbatim":
90
- let env = _printRaw(node.env);
91
- let envStart = [ESCAPE + "begin{", ...env, "}"];
92
- let envEnd = [ESCAPE + "end{", ...env, "}"];
93
- argsString = node.args == null ? [] : _printRaw(node.args);
94
- return [
95
- ...envStart,
96
- ...argsString,
97
- ..._printRaw(node.content),
98
- ...envEnd
99
- ];
100
- case "displaymath":
101
- return [ESCAPE + "[", ..._printRaw(node.content), ESCAPE + "]"];
102
- case "group":
103
- return ["{", ..._printRaw(node.content), "}"];
104
- case "inlinemath":
105
- return ["$", ..._printRaw(node.content), "$"];
106
- case "macro":
107
- argsString = node.args == null ? [] : _printRaw(node.args);
108
- escape = node.escapeToken == null ? ESCAPE : node.escapeToken;
109
- return [escape, ..._printRaw(node.content), ...argsString];
110
- case "parbreak":
111
- return [linebreak, linebreak];
112
- case "string":
113
- return [node.content];
114
- case "verb":
115
- return [
116
- ESCAPE,
117
- node.env,
118
- node.escape,
119
- ..._printRaw(node.content),
120
- node.escape
121
- ];
122
- case "whitespace":
123
- return [" "];
124
- default:
125
- console.warn(
126
- "Cannot find render for node ",
127
- node,
128
- `(of type ${typeof node})`
129
- );
130
- return ["" + node];
131
- }
132
- }
133
- function printRaw(node, options) {
134
- const asArray = options != null ? options.asArray : false;
135
- const printedTokens = _printRaw(node);
136
- if (asArray) {
137
- return printedTokens;
138
- }
139
- return printedTokens.map((x) => x === linebreak ? "\n" : x).join("");
140
- }
141
-
142
- // ../unified-latex-util-match/dist/index.js
143
- function createMacroMatcher(macros) {
144
- const macrosHash = Array.isArray(macros) ? macros.length > 0 ? typeof macros[0] === "string" ? Object.fromEntries(
145
- macros.map((macro2) => {
146
- if (typeof macro2 !== "string") {
147
- throw new Error("Wrong branch of map function");
148
- }
149
- return [macro2, {}];
150
- })
151
- ) : Object.fromEntries(
152
- macros.map((macro2) => {
153
- if (typeof macro2 === "string") {
154
- throw new Error("Wrong branch of map function");
155
- }
156
- if (macro2.escapeToken != null) {
157
- return [
158
- macro2.content,
159
- { escapeToken: macro2.escapeToken }
160
- ];
161
- }
162
- return [macro2.content, {}];
163
- })
164
- ) : {} : macros;
165
- return function matchAgainstMacros(node) {
166
- if (node == null || node.type !== "macro") {
167
- return false;
168
- }
169
- const spec = macrosHash[node.content];
170
- if (!spec) {
171
- return false;
172
- }
173
- if (typeof spec === "object" && "escapeToken" in spec) {
174
- return spec.escapeToken == null || spec.escapeToken === node.escapeToken;
175
- }
176
- return true;
177
- };
178
- }
179
- function createEnvironmentMatcher(macros) {
180
- const environmentsHash = Array.isArray(macros) ? Object.fromEntries(
181
- macros.map((str) => {
182
- return [str, {}];
183
- })
184
- ) : macros;
185
- return function matchAgainstEnvironments(node) {
186
- if (!match.anyEnvironment(node)) {
187
- return false;
188
- }
189
- const envName = printRaw(node.env);
190
- const spec = environmentsHash[envName];
191
- if (!spec) {
192
- return false;
193
- }
194
- return true;
195
- };
196
- }
197
- var match = {
198
- macro(node, macroName) {
199
- if (node == null) {
200
- return false;
201
- }
202
- return node.type === "macro" && (macroName == null || node.content === macroName);
203
- },
204
- anyMacro(node) {
205
- return match.macro(node);
206
- },
207
- environment(node, envName) {
208
- if (node == null) {
209
- return false;
210
- }
211
- return (node.type === "environment" || node.type === "mathenv") && (envName == null || printRaw(node.env) === envName);
212
- },
213
- anyEnvironment(node) {
214
- return match.environment(node);
215
- },
216
- comment(node) {
217
- if (node == null) {
218
- return false;
219
- }
220
- return node.type === "comment";
221
- },
222
- parbreak(node) {
223
- if (node == null) {
224
- return false;
225
- }
226
- return node.type === "parbreak";
227
- },
228
- whitespace(node) {
229
- if (node == null) {
230
- return false;
231
- }
232
- return node.type === "whitespace";
233
- },
234
- /**
235
- * Matches whitespace or a comment with leading whitespace.
236
- */
237
- whitespaceLike(node) {
238
- if (node == null) {
239
- return false;
240
- }
241
- return node.type === "whitespace" || node.type === "whitespace" && node.leadingWhitespace === true;
242
- },
243
- string(node, value) {
244
- if (node == null) {
245
- return false;
246
- }
247
- return node.type === "string" && (value == null || node.content === value);
248
- },
249
- anyString(node) {
250
- return match.string(node);
251
- },
252
- group(node) {
253
- if (node == null) {
254
- return false;
255
- }
256
- return node.type === "group";
257
- },
258
- argument(node) {
259
- if (node == null) {
260
- return false;
261
- }
262
- return node.type === "argument";
263
- },
264
- blankArgument(node) {
265
- if (!match.argument(node)) {
266
- return false;
267
- }
268
- return node.openMark === "" && node.closeMark === "" && node.content.length === 0;
269
- },
270
- math(node) {
271
- if (node == null) {
272
- return false;
273
- }
274
- return node.type === "displaymath" || node.type === "inlinemath";
275
- },
276
- createMacroMatcher,
277
- createEnvironmentMatcher
278
- };
279
- var {
280
- anyEnvironment,
281
- anyMacro,
282
- anyString,
283
- argument,
284
- blankArgument,
285
- comment,
286
- environment,
287
- group,
288
- macro,
289
- math,
290
- parbreak,
291
- string,
292
- whitespace
293
- } = match;
294
-
295
- // libs/regions.ts
296
24
  function refineRegions(regions) {
297
25
  const _regions = [...regions];
298
26
  _regions.sort((a, b) => a.start - b.start);
@@ -356,172 +84,6 @@ function splitByRegions(array, regionsRecord) {
356
84
  }
357
85
  return ret;
358
86
  }
359
-
360
- // ../unified-latex-util-visit/dist/index.js
361
- function listMathChildren(node) {
362
- const NULL_RETURN = { enter: [], leave: [] };
363
- if (Array.isArray(node)) {
364
- return NULL_RETURN;
365
- }
366
- if (match.math(node)) {
367
- return { enter: ["content"], leave: [] };
368
- }
369
- const renderInfo = node._renderInfo || {};
370
- if (renderInfo.inMathMode == null) {
371
- return NULL_RETURN;
372
- }
373
- if (match.macro(node)) {
374
- if (renderInfo.inMathMode === true) {
375
- return { enter: ["args"], leave: [] };
376
- } else if (renderInfo.inMathMode === false) {
377
- return { enter: [], leave: ["args"] };
378
- }
379
- }
380
- if (match.environment(node)) {
381
- if (renderInfo.inMathMode === true) {
382
- return { enter: ["content"], leave: [] };
383
- } else {
384
- return { enter: [], leave: ["content"] };
385
- }
386
- }
387
- return NULL_RETURN;
388
- }
389
- var CONTINUE = Symbol("continue");
390
- var SKIP = Symbol("skip");
391
- var EXIT = Symbol("exit");
392
- var DEFAULT_CONTEXT = {
393
- inMathMode: false,
394
- hasMathModeAncestor: false
395
- };
396
- function visit(tree, visitor, options) {
397
- const {
398
- startingContext = DEFAULT_CONTEXT,
399
- test = () => true,
400
- includeArrays = false
401
- } = options || {};
402
- let enter;
403
- let leave;
404
- if (typeof visitor === "function") {
405
- enter = visitor;
406
- } else if (visitor && typeof visitor === "object") {
407
- enter = visitor.enter;
408
- leave = visitor.leave;
409
- }
410
- walk(tree, {
411
- key: void 0,
412
- index: void 0,
413
- parents: [],
414
- containingArray: void 0,
415
- context: { ...startingContext }
416
- });
417
- function walk(node, { key, index, parents, context, containingArray }) {
418
- const nodePassesTest = includeArrays ? test(node, { key, index, parents, context, containingArray }) : !Array.isArray(node) && test(node, { key, index, parents, context, containingArray });
419
- const result = enter && nodePassesTest ? toResult(
420
- enter(node, {
421
- key,
422
- index,
423
- parents,
424
- context,
425
- containingArray
426
- })
427
- ) : [CONTINUE];
428
- if (result[0] === EXIT) {
429
- return result;
430
- }
431
- if (result[0] === SKIP) {
432
- return leave && nodePassesTest ? toResult(
433
- leave(node, {
434
- key,
435
- index,
436
- parents,
437
- context,
438
- containingArray
439
- })
440
- ) : result;
441
- }
442
- if (Array.isArray(node)) {
443
- for (let index2 = 0; index2 > -1 && index2 < node.length; index2++) {
444
- const item = node[index2];
445
- const result2 = walk(item, {
446
- key,
447
- index: index2,
448
- parents,
449
- context,
450
- containingArray: node
451
- });
452
- if (result2[0] === EXIT) {
453
- return result2;
454
- }
455
- if (typeof result2[1] === "number") {
456
- index2 = result2[1] - 1;
457
- }
458
- }
459
- } else {
460
- let childProps = ["content", "args"];
461
- switch (node.type) {
462
- case "macro":
463
- childProps = ["args"];
464
- break;
465
- case "comment":
466
- case "string":
467
- case "verb":
468
- case "verbatim":
469
- childProps = [];
470
- break;
471
- default:
472
- break;
473
- }
474
- const mathModeProps = listMathChildren(node);
475
- for (const key2 of childProps) {
476
- const value = node[key2];
477
- const grandparents = [node].concat(parents);
478
- if (value == null) {
479
- continue;
480
- }
481
- const newContext = { ...context };
482
- if (mathModeProps.enter.includes(key2)) {
483
- newContext.inMathMode = true;
484
- newContext.hasMathModeAncestor = true;
485
- } else if (mathModeProps.leave.includes(key2)) {
486
- newContext.inMathMode = false;
487
- }
488
- const result2 = walk(value, {
489
- key: key2,
490
- index: void 0,
491
- parents: grandparents,
492
- context: newContext,
493
- containingArray: void 0
494
- });
495
- if (result2[0] === EXIT) {
496
- return result2;
497
- }
498
- }
499
- }
500
- return leave && nodePassesTest ? toResult(
501
- leave(node, {
502
- key,
503
- index,
504
- parents,
505
- context,
506
- containingArray
507
- })
508
- ) : result;
509
- }
510
- }
511
- function toResult(value) {
512
- if (value == null) {
513
- return [CONTINUE];
514
- }
515
- if (Array.isArray(value)) {
516
- return value;
517
- }
518
- if (typeof value === "number") {
519
- return [CONTINUE, value];
520
- }
521
- return [value];
522
- }
523
-
524
- // libs/reparse-macro-names.ts
525
87
  function escapeRegExp(str) {
526
88
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
527
89
  }
@@ -531,12 +93,12 @@ function buildWordRegex(allowedSet) {
531
93
  }
532
94
  function hasReparsableMacroNamesInArray(tree, allowedTokens) {
533
95
  for (let i = 0; i < tree.length; i++) {
534
- const macro2 = tree[i];
535
- const string2 = tree[i + 1];
536
- if (match.anyMacro(macro2) && match.anyString(string2)) {
96
+ const macro = tree[i];
97
+ const string = tree[i + 1];
98
+ if (unifiedLatexUtilMatch.match.anyMacro(macro) && unifiedLatexUtilMatch.match.anyString(string)) {
537
99
  if (allowedTokens.has(
538
- macro2.content.charAt(macro2.content.length - 1)
539
- ) || allowedTokens.has(string2.content.charAt(0))) {
100
+ macro.content.charAt(macro.content.length - 1)
101
+ ) || allowedTokens.has(string.content.charAt(0))) {
540
102
  return true;
541
103
  }
542
104
  }
@@ -556,12 +118,12 @@ function hasReparsableMacroNames(tree, allowedTokens) {
556
118
  }
557
119
  }
558
120
  let ret = false;
559
- visit(
121
+ unifiedLatexUtilVisit.visit(
560
122
  tree,
561
123
  (nodes) => {
562
124
  if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {
563
125
  ret = true;
564
- return EXIT;
126
+ return unifiedLatexUtilVisit.EXIT;
565
127
  }
566
128
  },
567
129
  { includeArrays: true, test: Array.isArray }
@@ -573,34 +135,34 @@ function reparseMacroNamesInArray(tree, allowedTokens) {
573
135
  const regex = buildWordRegex(allowedTokens);
574
136
  let i = 0;
575
137
  while (i < tree.length) {
576
- const macro2 = tree[i];
577
- const string2 = tree[i + 1];
578
- if (match.anyMacro(macro2) && // The _^ macros in math mode should not be extended no-matter what;
138
+ const macro = tree[i];
139
+ const string = tree[i + 1];
140
+ if (unifiedLatexUtilMatch.match.anyMacro(macro) && // The _^ macros in math mode should not be extended no-matter what;
579
141
  // So we check to make sure that the macro we're dealing with has the default escape token.
580
- (macro2.escapeToken == null || macro2.escapeToken === "\\") && match.anyString(string2) && // There are two options. Either the macro ends with the special character,
142
+ (macro.escapeToken == null || macro.escapeToken === "\\") && unifiedLatexUtilMatch.match.anyString(string) && // There are two options. Either the macro ends with the special character,
581
143
  // e.g. `\@foo` or the special character starts the next string, e.g. `\foo@`.
582
144
  (allowedTokens.has(
583
- macro2.content.charAt(macro2.content.length - 1)
584
- ) || allowedTokens.has(string2.content.charAt(0)))) {
585
- const match2 = string2.content.match(regex);
145
+ macro.content.charAt(macro.content.length - 1)
146
+ ) || allowedTokens.has(string.content.charAt(0)))) {
147
+ const match2 = string.content.match(regex);
586
148
  const takeable = match2 ? match2[0] : "";
587
149
  if (takeable.length > 0) {
588
- if (takeable.length === string2.content.length) {
589
- macro2.content += string2.content;
150
+ if (takeable.length === string.content.length) {
151
+ macro.content += string.content;
590
152
  tree.splice(i + 1, 1);
591
- if (macro2.position && ((_a = string2.position) == null ? void 0 : _a.end)) {
592
- macro2.position.end = string2.position.end;
153
+ if (macro.position && ((_a = string.position) == null ? void 0 : _a.end)) {
154
+ macro.position.end = string.position.end;
593
155
  }
594
156
  } else {
595
- macro2.content += takeable;
596
- string2.content = string2.content.slice(takeable.length);
597
- if ((_b = macro2.position) == null ? void 0 : _b.end) {
598
- macro2.position.end.offset += takeable.length;
599
- macro2.position.end.column += takeable.length;
157
+ macro.content += takeable;
158
+ string.content = string.content.slice(takeable.length);
159
+ if ((_b = macro.position) == null ? void 0 : _b.end) {
160
+ macro.position.end.offset += takeable.length;
161
+ macro.position.end.column += takeable.length;
600
162
  }
601
- if ((_c = string2.position) == null ? void 0 : _c.start) {
602
- string2.position.start.offset += takeable.length;
603
- string2.position.start.column += takeable.length;
163
+ if ((_c = string.position) == null ? void 0 : _c.start) {
164
+ string.position.start.offset += takeable.length;
165
+ string.position.start.column += takeable.length;
604
166
  }
605
167
  }
606
168
  } else {
@@ -623,7 +185,7 @@ function reparseMacroNames(tree, allowedTokens) {
623
185
  );
624
186
  }
625
187
  }
626
- visit(
188
+ unifiedLatexUtilVisit.visit(
627
189
  tree,
628
190
  (nodes) => {
629
191
  reparseMacroNamesInArray(nodes, _allowedTokens);
@@ -631,15 +193,13 @@ function reparseMacroNames(tree, allowedTokens) {
631
193
  { includeArrays: true, test: Array.isArray }
632
194
  );
633
195
  }
634
-
635
- // libs/special-regions.ts
636
- var expl3Find = {
637
- start: match.createMacroMatcher(["ExplSyntaxOn"]),
638
- end: match.createMacroMatcher(["ExplSyntaxOff"])
196
+ const expl3Find = {
197
+ start: unifiedLatexUtilMatch.match.createMacroMatcher(["ExplSyntaxOn"]),
198
+ end: unifiedLatexUtilMatch.match.createMacroMatcher(["ExplSyntaxOff"])
639
199
  };
640
- var atLetterFind = {
641
- start: match.createMacroMatcher(["makeatletter"]),
642
- end: match.createMacroMatcher(["makeatother"])
200
+ const atLetterFind = {
201
+ start: unifiedLatexUtilMatch.match.createMacroMatcher(["makeatletter"]),
202
+ end: unifiedLatexUtilMatch.match.createMacroMatcher(["makeatother"])
643
203
  };
644
204
  function findExpl3AndAtLetterRegionsInArray(tree) {
645
205
  const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);
@@ -679,11 +239,11 @@ function findExpl3AndAtLetterRegionsInArray(tree) {
679
239
  ret.both = ret.both.filter((r) => r.end - r.start > 1);
680
240
  return ret;
681
241
  }
682
- var atLetterSet = /* @__PURE__ */ new Set(["@"]);
683
- var explSet = /* @__PURE__ */ new Set(["_", ":"]);
684
- var bothSet = /* @__PURE__ */ new Set(["_", ":", "@"]);
242
+ const atLetterSet = /* @__PURE__ */ new Set(["@"]);
243
+ const explSet = /* @__PURE__ */ new Set(["_", ":"]);
244
+ const bothSet = /* @__PURE__ */ new Set(["_", ":", "@"]);
685
245
  function reparseExpl3AndAtLetterRegions(tree) {
686
- visit(
246
+ unifiedLatexUtilVisit.visit(
687
247
  tree,
688
248
  {
689
249
  leave: (nodes) => {
@@ -719,10 +279,17 @@ function reparseExpl3AndAtLetterRegions(tree) {
719
279
  }
720
280
  nodes.length = 0;
721
281
  nodes.push(...processed);
722
- return SKIP;
282
+ return unifiedLatexUtilVisit.SKIP;
723
283
  }
724
284
  },
725
285
  { includeArrays: true, test: Array.isArray }
726
286
  );
727
287
  }
288
+ exports.findExpl3AndAtLetterRegionsInArray = findExpl3AndAtLetterRegionsInArray;
289
+ exports.findRegionInArray = findRegionInArray;
290
+ exports.hasReparsableMacroNames = hasReparsableMacroNames;
291
+ exports.hasReparsableMacroNamesInArray = hasReparsableMacroNamesInArray;
292
+ exports.reparseExpl3AndAtLetterRegions = reparseExpl3AndAtLetterRegions;
293
+ exports.reparseMacroNames = reparseMacroNames;
294
+ exports.reparseMacroNamesInArray = reparseMacroNamesInArray;
728
295
  //# sourceMappingURL=index.cjs.map
package/index.cjs.map CHANGED
@@ -1,7 +1 @@
1
- {
2
- "version": 3,
3
- "sources": ["../index.ts", "../libs/find-region.ts", "../../unified-latex-util-print-raw/libs/print-raw.ts", "../../unified-latex-util-match/libs/match.ts", "../libs/regions.ts", "../../unified-latex-util-visit/libs/list-math-children.ts", "../../unified-latex-util-visit/libs/visit.ts", "../libs/reparse-macro-names.ts", "../libs/special-regions.ts"],
4
- "sourcesContent": ["export * from \"./libs/find-region\";\nexport * from \"./libs/special-regions\";\nexport * from \"./libs/reparse-macro-names\";\n\n// NOTE: The docstring comment must be the last item in the index.ts file!\n/**\n * ## What is this?\n *\n * Functions to identify regions of a `unified-latex` Abstract Syntax Tree (AST) that need to be reparsed because of different\n * category codes. For example, regions between `\\makeatletter` and `\\makeatother`.\n *\n * ## When should I use this?\n *\n * If you need to identify regions of the AST that need to be reparsed.\n */\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { Region } from \"./regions\";\n\n/**\n * Find all contiguous segments in the array that are between start and end blocks.\n * The `start` and `end` are functions that determine when a region starts and ends.\n */\nexport function findRegionInArray(\n tree: Ast.Node[],\n start: (node: Ast.Node) => boolean,\n end: (node: Ast.Node) => boolean\n): Region[] {\n const ret: Region[] = [];\n let currRegion: Region = { start: undefined as any, end: tree.length };\n for (let i = 0; i < tree.length; i++) {\n const node = tree[i];\n if (start(node)) {\n currRegion.start = i;\n }\n if (end(node)) {\n currRegion.end = i + 1;\n ret.push(currRegion);\n currRegion = { start: undefined as any, end: tree.length };\n }\n }\n\n if (currRegion.start != null) {\n // Regions don't necessarily have to encounter an `end` to end.\n ret.push(currRegion);\n }\n return ret;\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\n\ntype Printable = Ast.Node | Ast.Argument | string;\ntype PrintToken = string | typeof linebreak;\n\nexport const linebreak = Symbol(\"linebreak\");\nconst ESCAPE = \"\\\\\";\n\n/**\n * Renders the AST to an array inserting `linebreak` where needed;\n * This array may be nested.\n *\n * @param {*} node\n */\nfunction _printRaw(node: Printable | Printable[]): PrintToken[] {\n if (typeof node === \"string\") {\n return [node];\n }\n if (Array.isArray(node)) {\n return ([] as PrintToken[]).concat(\n ...node.map((n: Printable) => _printRaw(n))\n );\n }\n // tmp variables\n let argsString, escape;\n switch (node.type) {\n case \"root\":\n return _printRaw(node.content);\n case \"argument\":\n return [node.openMark, ..._printRaw(node.content), node.closeMark];\n case \"comment\":\n let suffix = node.suffixParbreak ? \"\" : linebreak;\n // A comment is responsible for printing its own leading whitespace\n let leadingWhitespace = \"\";\n if (node.sameline && node.leadingWhitespace) {\n leadingWhitespace = \" \";\n }\n if (node.sameline) {\n return [\n leadingWhitespace,\n \"%\",\n ..._printRaw(node.content),\n suffix,\n ];\n }\n return [linebreak, \"%\", ..._printRaw(node.content), suffix];\n case \"environment\":\n case \"mathenv\":\n case \"verbatim\":\n let env = _printRaw(node.env);\n let envStart: PrintToken[] = [ESCAPE + \"begin{\", ...env, \"}\"];\n let envEnd: PrintToken[] = [ESCAPE + \"end{\", ...env, \"}\"];\n argsString =\n (node as any).args == null ? [] : _printRaw((node as any).args);\n return [\n ...envStart,\n ...argsString,\n ..._printRaw(node.content),\n ...envEnd,\n ];\n case \"displaymath\":\n return [ESCAPE + \"[\", ..._printRaw(node.content), ESCAPE + \"]\"];\n case \"group\":\n return [\"{\", ..._printRaw(node.content), \"}\"];\n case \"inlinemath\":\n return [\"$\", ..._printRaw(node.content), \"$\"];\n case \"macro\":\n argsString = node.args == null ? [] : _printRaw(node.args);\n escape = node.escapeToken == null ? ESCAPE : node.escapeToken;\n return [escape, ..._printRaw(node.content), ...argsString];\n case \"parbreak\":\n return [linebreak, linebreak];\n case \"string\":\n return [node.content];\n case \"verb\":\n return [\n ESCAPE,\n node.env,\n node.escape,\n ..._printRaw(node.content),\n node.escape,\n ];\n case \"whitespace\":\n return [\" \"];\n\n default:\n console.warn(\n \"Cannot find render for node \",\n node,\n `(of type ${typeof node})`\n );\n return [\"\" + node];\n }\n}\n\n/**\n * Renders the AST to a string without any pretty printing.\n *\n * @param {*} node\n * @param {*} options - Setting `asArray` to `true` will return an array of strings and the symbol `linebreak`, so that printing can be customized.\n */\nexport function printRaw(\n node: Printable | Printable[],\n options?: { asArray: false }\n): string;\nexport function printRaw(\n node: Printable | Printable[],\n options: { asArray: true }\n): PrintToken[];\nexport function printRaw(node: Printable | Printable[], options?: object): any {\n const asArray = options != null ? (options as any).asArray : false;\n const printedTokens = _printRaw(node);\n if (asArray) {\n return printedTokens;\n }\n return printedTokens.map((x) => (x === linebreak ? \"\\n\" : x)).join(\"\");\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\nimport {\n EnvInfo,\n MacroInfo,\n MacroInfoRecord,\n} from \"@unified-latex/unified-latex-types\";\nimport { printRaw } from \"@unified-latex/unified-latex-util-print-raw\";\n\n/**\n * Creates a macro matching function that uses a `SpecialMacroSpec` or list of macros\n * and generates a hash for quick lookup.\n */\nfunction createMacroMatcher<S extends string>(\n macros: Ast.Macro[] | S[] | Record<S, unknown>\n) {\n // We first make sure we have a record type with keys being the macro's contents\n const macrosHash: Record<string, unknown> = Array.isArray(macros)\n ? macros.length > 0\n ? typeof macros[0] === \"string\"\n ? Object.fromEntries(\n macros.map((macro) => {\n if (typeof macro !== \"string\") {\n throw new Error(\"Wrong branch of map function\");\n }\n return [macro, {}] as [string, MacroInfo];\n })\n )\n : Object.fromEntries(\n macros.map((macro) => {\n if (typeof macro === \"string\") {\n throw new Error(\"Wrong branch of map function\");\n }\n if (macro.escapeToken != null) {\n return [\n macro.content,\n { escapeToken: macro.escapeToken },\n ] as [string, MacroInfo];\n }\n return [macro.content, {}] as [string, MacroInfo];\n })\n )\n : {}\n : macros;\n\n return function matchAgainstMacros(node: any | Ast.Macro) {\n if (node == null || node.type !== \"macro\") {\n return false;\n }\n // At this point we have a macro type\n const spec = macrosHash[node.content];\n if (!spec) {\n return false;\n }\n\n if (typeof spec === \"object\" && \"escapeToken\" in spec) {\n return (\n (spec as MacroInfoRecord).escapeToken == null ||\n (spec as MacroInfoRecord).escapeToken === node.escapeToken\n );\n }\n return true;\n } as Ast.TypeGuard<Ast.Macro & { content: S }>;\n}\n\n/**\n * Creates a macro matching function that uses a `SpecialMacroSpec` or list of macros\n * and generates a hash for quick lookup.\n */\nfunction createEnvironmentMatcher(macros: string[] | Record<string, unknown>) {\n // We first make sure we have a record type with keys being the macro's contents\n const environmentsHash = Array.isArray(macros)\n ? Object.fromEntries(\n macros.map((str) => {\n return [str, {}] as [string, EnvInfo];\n })\n )\n : macros;\n\n return function matchAgainstEnvironments(node: any | Ast.Environment) {\n if (!match.anyEnvironment(node)) {\n return false;\n }\n // At this point we have an environment type\n const envName = printRaw(node.env);\n const spec = environmentsHash[envName];\n if (!spec) {\n return false;\n }\n\n return true;\n } as Ast.TypeGuard<Ast.Environment>;\n}\n\n/**\n * Functions to match different types of nodes.\n */\nexport const match = {\n macro(node: any, macroName?: string): node is Ast.Macro {\n if (node == null) {\n return false;\n }\n return (\n node.type === \"macro\" &&\n (macroName == null || node.content === macroName)\n );\n },\n anyMacro(node: any): node is Ast.Macro {\n return match.macro(node);\n },\n environment(node: any, envName?: string): node is Ast.Environment {\n if (node == null) {\n return false;\n }\n return (\n (node.type === \"environment\" || node.type === \"mathenv\") &&\n (envName == null || printRaw(node.env) === envName)\n );\n },\n anyEnvironment(node: any): node is Ast.Environment {\n return match.environment(node);\n },\n comment(node: any): node is Ast.Comment {\n if (node == null) {\n return false;\n }\n return node.type === \"comment\";\n },\n parbreak(node: any): node is Ast.Parbreak {\n if (node == null) {\n return false;\n }\n return node.type === \"parbreak\";\n },\n whitespace(node: any): node is Ast.Whitespace {\n if (node == null) {\n return false;\n }\n return node.type === \"whitespace\";\n },\n /**\n * Matches whitespace or a comment with leading whitespace.\n */\n whitespaceLike(\n node: any\n ): node is Ast.Whitespace | (Ast.Comment & { leadingWhitespace: true }) {\n if (node == null) {\n return false;\n }\n return (\n node.type === \"whitespace\" ||\n (node.type === \"whitespace\" && node.leadingWhitespace === true)\n );\n },\n string(node: any, value?: string): node is Ast.String {\n if (node == null) {\n return false;\n }\n return (\n node.type === \"string\" && (value == null || node.content === value)\n );\n },\n anyString(node: any): node is Ast.String {\n return match.string(node);\n },\n group(node: any): node is Ast.Group {\n if (node == null) {\n return false;\n }\n return node.type === \"group\";\n },\n argument(node: any): node is Ast.Argument {\n if (node == null) {\n return false;\n }\n return node.type === \"argument\";\n },\n blankArgument(node: any): boolean {\n if (!match.argument(node)) {\n return false;\n }\n return (\n node.openMark === \"\" &&\n node.closeMark === \"\" &&\n node.content.length === 0\n );\n },\n math(node: any): node is Ast.DisplayMath | Ast.InlineMath {\n if (node == null) {\n return false;\n }\n return node.type === \"displaymath\" || node.type === \"inlinemath\";\n },\n createMacroMatcher,\n createEnvironmentMatcher,\n};\n\nexport const {\n anyEnvironment,\n anyMacro,\n anyString,\n argument,\n blankArgument,\n comment,\n environment,\n group,\n macro,\n math,\n parbreak,\n string,\n whitespace,\n} = match;\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\n\nexport type Region = { start: number; end: number };\n\n/**\n * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,\n * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region\n * is a subset of.\n */\nexport function refineRegions(regions: Region[]): {\n regions: Region[];\n regionsContainedIn: Set<Region>[];\n} {\n const _regions = [...regions];\n _regions.sort((a, b) => a.start - b.start);\n const cutPointsSet = new Set(_regions.flatMap((r) => [r.start, r.end]));\n const cutPoints = Array.from(cutPointsSet);\n cutPoints.sort((a, b) => a - b);\n\n const retRegions: Region[] = [];\n const retRegionsContainedIn: Set<Region>[] = [];\n\n // We will be checking what regions we are completely contained in.\n // Because `_regions` is sorted by start, `seekIndex` will be incremented\n // by end, so that we don't do too much array testing.\n let seekIndex = 0;\n for (let i = 0; i < cutPoints.length - 1; i++) {\n const start = cutPoints[i];\n const end = cutPoints[i + 1];\n const region = { start, end };\n const regionContainedIn: Set<Region> = new Set();\n\n let encounteredEndPastStart = false;\n for (let j = seekIndex; j < _regions.length; j++) {\n const superRegion = _regions[j];\n if (superRegion.end >= region.start) {\n encounteredEndPastStart = true;\n }\n if (!encounteredEndPastStart && superRegion.end < region.start) {\n // In this case, the region (and all regions that came before)\n // end before the region we are testing, so we may safely skip past it\n // from here on out.\n seekIndex = j + 1;\n continue;\n }\n\n if (superRegion.start > end) {\n // Because `_regions` is sorted, we can stop here\n break;\n }\n if (\n superRegion.start <= region.start &&\n superRegion.end >= region.end\n ) {\n encounteredEndPastStart = true;\n regionContainedIn.add(superRegion);\n }\n }\n\n if (regionContainedIn.size > 0) {\n // We only count if we are contained in a subregion\n retRegions.push(region);\n retRegionsContainedIn.push(regionContainedIn);\n }\n }\n\n return { regions: retRegions, regionsContainedIn: retRegionsContainedIn };\n}\n\n/**\n * Split an array up into the disjoint regions specified by `regionRecord`.\n * Returned is a list of tuples, the first item being the key of `regionRecord` if there\n * was a corresponding region, or `null` if there was no corresponding region.\n *\n * This function assumes that the regions in `regionRecord` are disjoint and fully contained\n * within the bounds of `array`.\n */\nexport function splitByRegions<\n T,\n RegionRecord extends Record<string, Region[]>,\n>(array: T[], regionsRecord: RegionRecord) {\n const ret: [keyof RegionRecord | null, T[]][] = [];\n\n const indices = [0, array.length];\n const reverseMap: Record<string, keyof RegionRecord> = {};\n for (const [key, records] of Object.entries(regionsRecord)) {\n indices.push(\n ...records.flatMap((r) => {\n reverseMap[\"\" + [r.start, r.end]] = key;\n return [r.start, r.end];\n })\n );\n }\n indices.sort((a, b) => a - b);\n\n for (let i = 0; i < indices.length - 1; i++) {\n const start = indices[i];\n const end = indices[i + 1];\n if (start === end) {\n continue;\n }\n const regionKey = reverseMap[\"\" + [start, end]];\n\n ret.push([regionKey || null, array.slice(start, end)]);\n }\n\n return ret;\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\n\n/**\n * List all props of the current node that should be processed\n * in math mode or not in math mode. If math mode is not specified in the node's render\n * info, empty lists are returned.\n *\n * For example `\\text{foo}` will report that `args` should *not* be processed in math mode,\n * since it's contents should always be processed in text mode.\n */\nexport function listMathChildren(node: Ast.Ast): {\n enter: string[];\n leave: string[];\n} {\n const NULL_RETURN = { enter: [], leave: [] };\n if (Array.isArray(node)) {\n return NULL_RETURN;\n }\n if (match.math(node)) {\n // When we enter a math environment, our content is always\n // considered math mode\n return { enter: [\"content\"], leave: [] };\n }\n\n const renderInfo: { inMathMode?: boolean } = node._renderInfo || {};\n if (renderInfo.inMathMode == null) {\n return NULL_RETURN;\n }\n if (match.macro(node)) {\n if (renderInfo.inMathMode === true) {\n return { enter: [\"args\"], leave: [] };\n } else if (renderInfo.inMathMode === false) {\n return { enter: [], leave: [\"args\"] };\n }\n }\n if (match.environment(node)) {\n if (renderInfo.inMathMode === true) {\n return { enter: [\"content\"], leave: [] };\n } else {\n return { enter: [], leave: [\"content\"] };\n }\n }\n return NULL_RETURN;\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { listMathChildren } from \"./list-math-children\";\n\nexport type VisitorContext = {\n /**\n * Whether the node is being processed in math mode.\n *\n * This happens when the node is a director or indirect child\n * of a math environment (e.g. `$abc$`), but not when an environment\n * re-establishes text mode (e.g. `$\\text{abc}$`)\n */\n inMathMode?: boolean;\n /**\n * Whether the node has any ancestor that is processed in math mode.\n */\n hasMathModeAncestor?: boolean;\n};\n\ntype GetGuard<T> = T extends (x: any, ...y: any[]) => x is infer R ? R : never;\n/**\n * Gets the type that a type-guard function is guarding. If\n * the guard type cannot be determined, the input type is returned.\n */\ntype GuardTypeOf<T extends (x: any, ...y: any[]) => boolean> =\n GetGuard<T> extends never\n ? T extends (x: infer A) => any\n ? A\n : never\n : GetGuard<T>;\n\n/**\n * Extracts the guard type from the `test` function provided in a\n * `VisitOptions` argument.\n */\ntype GuardFromOptions<\n Opts extends VisitOptions,\n PossibleTypes = Ast.Ast,\n> = Opts extends {\n test: infer R;\n}\n ? R extends (x: any, ...y: any[]) => boolean\n ? // A guard like `typeof Array.isArray` will return `any[]` as the type.\n // This type cannot be narrowed, so instead we use it to pick from\n // the set of all possible types.\n Extract<PossibleTypes, GuardTypeOf<R>>\n : PossibleTypes\n : PossibleTypes;\n\n/**\n * Narrow the type `T` based on the `VisitOptions` supplied. If `{includeArrays: false}`\n * is specified in the `VisitOptions`, then arrays are excluded from `T`.\n */\ntype NarrowArraysBasedOnOptions<T, Opts extends VisitOptions> = Opts extends {\n includeArrays: infer A;\n}\n ? A extends true\n ? T\n : Exclude<T, any[]>\n : Exclude<T, any[]>;\n\n/**\n * Get the type of the parameter to the `Visitor` function based on the\n * `VisitOptions` that are supplied.\n */\ntype VisitorTypeFromOptions<Opts extends VisitOptions> =\n NarrowArraysBasedOnOptions<GuardFromOptions<Opts>, Opts>;\n\n/**\n * Continue traversing as normal\n */\nexport const CONTINUE = Symbol(\"continue\");\n/**\n * Do not traverse this node\u2019s children\n */\nexport const SKIP = Symbol(\"skip\");\n/**\n * Stop traversing immediately\n */\nexport const EXIT = Symbol(\"exit\");\n\ntype Action = typeof CONTINUE | typeof SKIP | typeof EXIT;\ntype Index = number;\ntype ActionTuple = [Action] | [typeof SKIP, Index] | [typeof CONTINUE, Index];\n\n/**\n * A visitor takes a `node`, `key`, `index`, and ...\n *\n * @param key - The key of the parent that we were accessed through.\n */\ntype Visitor<T> = (\n node: T,\n info: VisitInfo\n) => null | undefined | Action | Index | ActionTuple | void;\ntype Visitors<T> = { enter?: Visitor<T>; leave?: Visitor<T> };\n\ntype VisitOptions = {\n startingContext?: VisitorContext;\n /**\n * Type guard for types that are passed to the `visitor` function.\n */\n test?: (node: Ast.Ast, info: VisitInfo) => boolean;\n /**\n * Whether arrays will be sent to the `visitor` function. If falsy,\n * only nodes will be past to `visitor`.\n */\n includeArrays?: boolean;\n};\n\nconst DEFAULT_CONTEXT: VisitorContext = {\n inMathMode: false,\n hasMathModeAncestor: false,\n};\n\nexport type VisitInfo = {\n /**\n * If the element was accessed via an attribute, the attribute key is specified.\n */\n readonly key: string | undefined;\n /**\n * If the element was accessed in an array, the index is specified.\n */\n readonly index: number | undefined;\n /**\n * A list of ancestor nodes, `[parent, grandparent, great-grandparent, ...]`\n */\n readonly parents: (Ast.Node | Ast.Argument)[];\n /**\n * If the element was accessed in an array, the array that it is part of.\n */\n readonly containingArray: (Ast.Node | Ast.Argument)[] | undefined;\n /**\n * The LaTeX context of the current match.\n */\n readonly context: VisitorContext;\n};\n\n/**\n * Visit children of tree which pass a test\n *\n * @param {Node} tree Abstract syntax tree to walk\n * @param {Visitor|Visitors} [visitor] Function to run for each node\n */\nexport function visit<Opts extends VisitOptions>(\n tree: Ast.Ast,\n visitor:\n | Visitor<VisitorTypeFromOptions<Opts>>\n | Visitors<VisitorTypeFromOptions<Opts>>,\n options?: Opts\n) {\n const {\n startingContext = DEFAULT_CONTEXT,\n test = () => true,\n includeArrays = false,\n } = options || {};\n let enter: Visitor<VisitorTypeFromOptions<Opts>> | undefined;\n let leave: Visitor<VisitorTypeFromOptions<Opts>> | undefined;\n\n if (typeof visitor === \"function\") {\n enter = visitor;\n } else if (visitor && typeof visitor === \"object\") {\n enter = visitor.enter;\n leave = visitor.leave;\n }\n\n walk(tree, {\n key: undefined,\n index: undefined,\n parents: [],\n containingArray: undefined,\n context: { ...startingContext },\n });\n\n /**\n * @param {Node} node\n * @param {string?} key\n * @param {number?} index\n * @param {Array.<Node>} parents\n */\n function walk(\n node: Ast.Ast,\n { key, index, parents, context, containingArray }: VisitInfo\n ): ActionTuple {\n const nodePassesTest = includeArrays\n ? test(node, { key, index, parents, context, containingArray })\n : !Array.isArray(node) &&\n test(node, { key, index, parents, context, containingArray });\n\n const result: ActionTuple =\n enter && nodePassesTest\n ? toResult(\n enter(node as any, {\n key,\n index,\n parents,\n context,\n containingArray,\n })\n )\n : [CONTINUE];\n\n if (result[0] === EXIT) {\n return result;\n }\n\n if (result[0] === SKIP) {\n return leave && nodePassesTest\n ? toResult(\n leave(node as any, {\n key,\n index,\n parents,\n context,\n containingArray,\n })\n )\n : result;\n }\n\n if (Array.isArray(node)) {\n // The `value` array might be modified in place as we traverse it, so\n // we use a traditional for loop.\n for (let index = 0; index > -1 && index < node.length; index++) {\n const item = node[index];\n const result = walk(item, {\n key,\n index,\n parents,\n context,\n containingArray: node,\n });\n if (result[0] === EXIT) {\n return result;\n }\n if (typeof result[1] === \"number\") {\n // The for loop will increment i every pass. However,\n // if an index was returned, that's where we want to start next time.\n index = result[1] - 1;\n }\n }\n } else {\n // We don't want to recursively apply to the `content`\n // of all types (e.g., comments and macros), so specify\n // a blacklist.\n let childProps: (\"content\" | \"args\")[] = [\"content\", \"args\"];\n switch (node.type) {\n case \"macro\":\n childProps = [\"args\"];\n break;\n case \"comment\":\n case \"string\":\n case \"verb\":\n case \"verbatim\":\n childProps = [];\n break;\n default:\n break;\n }\n\n const mathModeProps = listMathChildren(node);\n for (const key of childProps) {\n const value = node[key as keyof typeof node] as\n | Ast.Ast\n | undefined;\n const grandparents = [node].concat(parents);\n\n if (value == null) {\n continue;\n }\n\n // We may switch in/out of math mode as we pass to node[key]\n const newContext = { ...context };\n if (mathModeProps.enter.includes(key)) {\n newContext.inMathMode = true;\n newContext.hasMathModeAncestor = true;\n } else if (mathModeProps.leave.includes(key)) {\n newContext.inMathMode = false;\n }\n\n const result = walk(value, {\n key,\n index: undefined,\n parents: grandparents,\n context: newContext,\n containingArray: undefined,\n });\n if (result[0] === EXIT) {\n return result;\n }\n }\n }\n\n return leave && nodePassesTest\n ? toResult(\n leave(node as any, {\n key,\n index,\n parents,\n context,\n containingArray,\n })\n )\n : result;\n }\n}\n\n/**\n * Ensures a result is an `ActionTuple`s\n */\nfunction toResult(\n value: null | undefined | void | Action | Index | ActionTuple\n): ActionTuple {\n if (value == null) {\n return [CONTINUE];\n }\n\n if (Array.isArray(value)) {\n return value;\n }\n\n if (typeof value === \"number\") {\n return [CONTINUE, value];\n }\n\n return [value];\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { EXIT, visit } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Escape a string so that it can be used to build a regular expression.\n *\n * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nfunction escapeRegExp(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\n/**\n * Build a regular expression that matches everything up to the first non-allowed symbol.\n */\nfunction buildWordRegex(allowedSet: Set<string>): RegExp {\n // /\\p{L}/ matches all letters, including unicode letters. We join this with\n // everything allowed in our set to form a regexp like\n // /(\\p{L}|_|:)*/u\n // The `u` at the end allows unicode characters to be matched.\n const regexpStr = `^(${[\"\\\\p{L}\"]\n .concat(Array.from(allowedSet).map(escapeRegExp))\n .join(\"|\")})*`;\n return new RegExp(regexpStr, \"u\");\n}\n\n/**\n * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n): boolean {\n for (let i = 0; i < tree.length; i++) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (match.anyMacro(macro) && match.anyString(string)) {\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n if (\n allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n): boolean {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n let ret = false;\n visit(\n tree,\n (nodes) => {\n if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {\n ret = true;\n return EXIT;\n }\n },\n { includeArrays: true, test: Array.isArray }\n );\n return ret;\n}\n\n/**\n * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name).\n */\nexport function reparseMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n) {\n const regex = buildWordRegex(allowedTokens);\n let i = 0;\n while (i < tree.length) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (\n match.anyMacro(macro) &&\n // The _^ macros in math mode should not be extended no-matter what;\n // So we check to make sure that the macro we're dealing with has the default escape token.\n (macro.escapeToken == null || macro.escapeToken === \"\\\\\") &&\n match.anyString(string) &&\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n (allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0)))\n ) {\n // There might be a number somewhere in the string. If so, we should\n // break the string apart at that number\n const match = string.content.match(regex);\n const takeable = match ? match[0] : \"\";\n if (takeable.length > 0) {\n if (takeable.length === string.content.length) {\n // The whole string can be appended to the macro name\n macro.content += string.content;\n tree.splice(i + 1, 1);\n\n // Preserve the source location if available\n if (macro.position && string.position?.end) {\n macro.position.end = string.position.end;\n }\n } else {\n // Only part of the string can be appended to the macro name\n macro.content += takeable;\n string.content = string.content.slice(takeable.length);\n\n // Preserve the source location if available\n if (macro.position?.end) {\n macro.position.end.offset += takeable.length;\n macro.position.end.column += takeable.length;\n }\n if (string.position?.start) {\n string.position.start.offset += takeable.length;\n string.position.start.column += takeable.length;\n }\n }\n } else {\n i++;\n }\n } else {\n ++i;\n }\n }\n}\n\n/**\n * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name). Thus, a macro `\\foo_bar:Nn` would be parsed as having\n * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.\n */\nexport function reparseMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n) {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n visit(\n tree,\n (nodes) => {\n reparseMacroNamesInArray(nodes, _allowedTokens);\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { findRegionInArray } from \"./find-region\";\nimport { refineRegions, Region, splitByRegions } from \"./regions\";\nimport { SKIP, visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { reparseMacroNames } from \"./reparse-macro-names\";\n\nconst expl3Find = {\n start: match.createMacroMatcher([\"ExplSyntaxOn\"]),\n end: match.createMacroMatcher([\"ExplSyntaxOff\"]),\n};\nconst atLetterFind = {\n start: match.createMacroMatcher([\"makeatletter\"]),\n end: match.createMacroMatcher([\"makeatother\"]),\n};\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`.\n * Returns an object containing regions where one or both syntax's apply.\n */\nexport function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {\n explOnly: Region[];\n atLetterOnly: Region[];\n both: Region[];\n} {\n const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);\n const atLetter = findRegionInArray(\n tree,\n atLetterFind.start,\n atLetterFind.end\n );\n\n const regionMap = new Map([\n ...(expl3.map((x) => [x, \"expl\"]) as [Region, \"expl\"][]),\n ...(atLetter.map((x) => [x, \"atLetter\"]) as [Region, \"atLetter\"][]),\n ]);\n const all = refineRegions([...expl3, ...atLetter]);\n\n const ret = {\n explOnly: [] as Region[],\n atLetterOnly: [] as Region[],\n both: [] as Region[],\n };\n\n for (let i = 0; i < all.regions.length; i++) {\n const region = all.regions[i];\n const containedIn = all.regionsContainedIn[i];\n if (containedIn.size === 2) {\n ret.both.push(region);\n continue;\n }\n for (const v of containedIn.values()) {\n if (regionMap.get(v) === \"expl\") {\n ret.explOnly.push(region);\n }\n if (regionMap.get(v) === \"atLetter\") {\n ret.atLetterOnly.push(region);\n }\n }\n }\n\n // Regions of size 1 only contain the starting/stopping macro, so they should be discarded\n ret.explOnly = ret.explOnly.filter((r) => r.end - r.start > 1);\n ret.atLetterOnly = ret.atLetterOnly.filter((r) => r.end - r.start > 1);\n ret.both = ret.both.filter((r) => r.end - r.start > 1);\n\n return ret;\n}\n\nconst atLetterSet = new Set([\"@\"]);\nconst explSet = new Set([\"_\", \":\"]);\nconst bothSet = new Set([\"_\", \":\", \"@\"]);\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`\n * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become\n * part of the macro names.\n */\nexport function reparseExpl3AndAtLetterRegions(tree: Ast.Ast) {\n visit(\n tree,\n {\n leave: (nodes) => {\n const regions = findExpl3AndAtLetterRegionsInArray(nodes);\n // In all likelihood, we don't need to do any reparsing, so bail early here\n const totalNumRegions =\n regions.both.length +\n regions.atLetterOnly.length +\n regions.explOnly.length;\n if (totalNumRegions === 0) {\n return;\n }\n\n const splits = splitByRegions(nodes, regions);\n const processed: typeof nodes = [];\n for (const [key, slice] of splits) {\n switch (key) {\n case null:\n processed.push(...slice);\n continue;\n case \"atLetterOnly\":\n reparseMacroNames(slice, atLetterSet);\n processed.push(...slice);\n continue;\n case \"explOnly\":\n reparseMacroNames(slice, explSet);\n processed.push(...slice);\n continue;\n case \"both\":\n reparseMacroNames(slice, bothSet);\n processed.push(...slice);\n continue;\n default:\n throw new Error(\n `Unexpected case when splitting ${key}`\n );\n }\n }\n\n nodes.length = 0;\n nodes.push(...processed);\n return SKIP;\n },\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n"],
5
- "mappings": "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",
6
- "names": ["macro", "index", "result", "key", "macro", "string", "match"]
7
- }
1
+ {"version":3,"file":"index.cjs","sources":["../libs/find-region.ts","../libs/regions.ts","../libs/reparse-macro-names.ts","../libs/special-regions.ts"],"sourcesContent":["import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { Region } from \"./regions\";\n\n/**\n * Find all contiguous segments in the array that are between start and end blocks.\n * The `start` and `end` are functions that determine when a region starts and ends.\n */\nexport function findRegionInArray(\n tree: Ast.Node[],\n start: (node: Ast.Node) => boolean,\n end: (node: Ast.Node) => boolean\n): Region[] {\n const ret: Region[] = [];\n let currRegion: Region = { start: undefined as any, end: tree.length };\n for (let i = 0; i < tree.length; i++) {\n const node = tree[i];\n if (start(node)) {\n currRegion.start = i;\n }\n if (end(node)) {\n currRegion.end = i + 1;\n ret.push(currRegion);\n currRegion = { start: undefined as any, end: tree.length };\n }\n }\n\n if (currRegion.start != null) {\n // Regions don't necessarily have to encounter an `end` to end.\n ret.push(currRegion);\n }\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\n\nexport type Region = { start: number; end: number };\n\n/**\n * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,\n * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region\n * is a subset of.\n */\nexport function refineRegions(regions: Region[]): {\n regions: Region[];\n regionsContainedIn: Set<Region>[];\n} {\n const _regions = [...regions];\n _regions.sort((a, b) => a.start - b.start);\n const cutPointsSet = new Set(_regions.flatMap((r) => [r.start, r.end]));\n const cutPoints = Array.from(cutPointsSet);\n cutPoints.sort((a, b) => a - b);\n\n const retRegions: Region[] = [];\n const retRegionsContainedIn: Set<Region>[] = [];\n\n // We will be checking what regions we are completely contained in.\n // Because `_regions` is sorted by start, `seekIndex` will be incremented\n // by end, so that we don't do too much array testing.\n let seekIndex = 0;\n for (let i = 0; i < cutPoints.length - 1; i++) {\n const start = cutPoints[i];\n const end = cutPoints[i + 1];\n const region = { start, end };\n const regionContainedIn: Set<Region> = new Set();\n\n let encounteredEndPastStart = false;\n for (let j = seekIndex; j < _regions.length; j++) {\n const superRegion = _regions[j];\n if (superRegion.end >= region.start) {\n encounteredEndPastStart = true;\n }\n if (!encounteredEndPastStart && superRegion.end < region.start) {\n // In this case, the region (and all regions that came before)\n // end before the region we are testing, so we may safely skip past it\n // from here on out.\n seekIndex = j + 1;\n continue;\n }\n\n if (superRegion.start > end) {\n // Because `_regions` is sorted, we can stop here\n break;\n }\n if (\n superRegion.start <= region.start &&\n superRegion.end >= region.end\n ) {\n encounteredEndPastStart = true;\n regionContainedIn.add(superRegion);\n }\n }\n\n if (regionContainedIn.size > 0) {\n // We only count if we are contained in a subregion\n retRegions.push(region);\n retRegionsContainedIn.push(regionContainedIn);\n }\n }\n\n return { regions: retRegions, regionsContainedIn: retRegionsContainedIn };\n}\n\n/**\n * Split an array up into the disjoint regions specified by `regionRecord`.\n * Returned is a list of tuples, the first item being the key of `regionRecord` if there\n * was a corresponding region, or `null` if there was no corresponding region.\n *\n * This function assumes that the regions in `regionRecord` are disjoint and fully contained\n * within the bounds of `array`.\n */\nexport function splitByRegions<\n T,\n RegionRecord extends Record<string, Region[]>\n>(array: T[], regionsRecord: RegionRecord) {\n const ret: [keyof RegionRecord | null, T[]][] = [];\n\n const indices = [0, array.length];\n const reverseMap: Record<string, keyof RegionRecord> = {};\n for (const [key, records] of Object.entries(regionsRecord)) {\n indices.push(\n ...records.flatMap((r) => {\n reverseMap[\"\" + [r.start, r.end]] = key;\n return [r.start, r.end];\n })\n );\n }\n indices.sort((a, b) => a - b);\n\n for (let i = 0; i < indices.length - 1; i++) {\n const start = indices[i];\n const end = indices[i + 1];\n if (start === end) {\n continue;\n }\n const regionKey = reverseMap[\"\" + [start, end]];\n\n ret.push([regionKey || null, array.slice(start, end)]);\n }\n\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { EXIT, visit } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Escape a string so that it can be used to build a regular expression.\n *\n * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nfunction escapeRegExp(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\n/**\n * Build a regular expression that matches everything up to the first non-allowed symbol.\n */\nfunction buildWordRegex(allowedSet: Set<string>): RegExp {\n // /\\p{L}/ matches all letters, including unicode letters. We join this with\n // everything allowed in our set to form a regexp like\n // /(\\p{L}|_|:)*/u\n // The `u` at the end allows unicode characters to be matched.\n const regexpStr = `^(${[\"\\\\p{L}\"]\n .concat(Array.from(allowedSet).map(escapeRegExp))\n .join(\"|\")})*`;\n return new RegExp(regexpStr, \"u\");\n}\n\n/**\n * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n): boolean {\n for (let i = 0; i < tree.length; i++) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (match.anyMacro(macro) && match.anyString(string)) {\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n if (\n allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n): boolean {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n let ret = false;\n visit(\n tree,\n (nodes) => {\n if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {\n ret = true;\n return EXIT;\n }\n },\n { includeArrays: true, test: Array.isArray }\n );\n return ret;\n}\n\n/**\n * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name).\n */\nexport function reparseMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n) {\n const regex = buildWordRegex(allowedTokens);\n let i = 0;\n while (i < tree.length) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (\n match.anyMacro(macro) &&\n // The _^ macros in math mode should not be extended no-matter what;\n // So we check to make sure that the macro we're dealing with has the default escape token.\n (macro.escapeToken == null || macro.escapeToken === \"\\\\\") &&\n match.anyString(string) &&\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n (allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0)))\n ) {\n // There might be a number somewhere in the string. If so, we should\n // break the string apart at that number\n const match = string.content.match(regex);\n const takeable = match ? match[0] : \"\";\n if (takeable.length > 0) {\n if (takeable.length === string.content.length) {\n // The whole string can be appended to the macro name\n macro.content += string.content;\n tree.splice(i + 1, 1);\n\n // Preserve the source location if available\n if (macro.position && string.position?.end) {\n macro.position.end = string.position.end;\n }\n } else {\n // Only part of the string can be appended to the macro name\n macro.content += takeable;\n string.content = string.content.slice(takeable.length);\n\n // Preserve the source location if available\n if (macro.position?.end) {\n macro.position.end.offset += takeable.length;\n macro.position.end.column += takeable.length;\n }\n if (string.position?.start) {\n string.position.start.offset += takeable.length;\n string.position.start.column += takeable.length;\n }\n }\n } else {\n i++;\n }\n } else {\n ++i;\n }\n }\n}\n\n/**\n * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name). Thus, a macro `\\foo_bar:Nn` would be parsed as having\n * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.\n */\nexport function reparseMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n) {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n visit(\n tree,\n (nodes) => {\n reparseMacroNamesInArray(nodes, _allowedTokens);\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { findRegionInArray } from \"./find-region\";\nimport { refineRegions, Region, splitByRegions } from \"./regions\";\nimport { SKIP, visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { reparseMacroNames } from \"./reparse-macro-names\";\n\nconst expl3Find = {\n start: match.createMacroMatcher([\"ExplSyntaxOn\"]),\n end: match.createMacroMatcher([\"ExplSyntaxOff\"]),\n};\nconst atLetterFind = {\n start: match.createMacroMatcher([\"makeatletter\"]),\n end: match.createMacroMatcher([\"makeatother\"]),\n};\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`.\n * Returns an object containing regions where one or both syntax's apply.\n */\nexport function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {\n explOnly: Region[];\n atLetterOnly: Region[];\n both: Region[];\n} {\n const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);\n const atLetter = findRegionInArray(\n tree,\n atLetterFind.start,\n atLetterFind.end\n );\n\n const regionMap = new Map([\n ...(expl3.map((x) => [x, \"expl\"]) as [Region, \"expl\"][]),\n ...(atLetter.map((x) => [x, \"atLetter\"]) as [Region, \"atLetter\"][]),\n ]);\n const all = refineRegions([...expl3, ...atLetter]);\n\n const ret = {\n explOnly: [] as Region[],\n atLetterOnly: [] as Region[],\n both: [] as Region[],\n };\n\n for (let i = 0; i < all.regions.length; i++) {\n const region = all.regions[i];\n const containedIn = all.regionsContainedIn[i];\n if (containedIn.size === 2) {\n ret.both.push(region);\n continue;\n }\n for (const v of containedIn.values()) {\n if (regionMap.get(v) === \"expl\") {\n ret.explOnly.push(region);\n }\n if (regionMap.get(v) === \"atLetter\") {\n ret.atLetterOnly.push(region);\n }\n }\n }\n\n // Regions of size 1 only contain the starting/stopping macro, so they should be discarded\n ret.explOnly = ret.explOnly.filter((r) => r.end - r.start > 1);\n ret.atLetterOnly = ret.atLetterOnly.filter((r) => r.end - r.start > 1);\n ret.both = ret.both.filter((r) => r.end - r.start > 1);\n\n return ret;\n}\n\nconst atLetterSet = new Set([\"@\"]);\nconst explSet = new Set([\"_\", \":\"]);\nconst bothSet = new Set([\"_\", \":\", \"@\"]);\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`\n * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become\n * part of the macro names.\n */\nexport function reparseExpl3AndAtLetterRegions(tree: Ast.Ast) {\n visit(\n tree,\n {\n leave: (nodes) => {\n const regions = findExpl3AndAtLetterRegionsInArray(nodes);\n // In all likelihood, we don't need to do any reparsing, so bail early here\n const totalNumRegions =\n regions.both.length +\n regions.atLetterOnly.length +\n regions.explOnly.length;\n if (totalNumRegions === 0) {\n return;\n }\n\n const splits = splitByRegions(nodes, regions);\n const processed: typeof nodes = [];\n for (const [key, slice] of splits) {\n switch (key) {\n case null:\n processed.push(...slice);\n continue;\n case \"atLetterOnly\":\n reparseMacroNames(slice, atLetterSet);\n processed.push(...slice);\n continue;\n case \"explOnly\":\n reparseMacroNames(slice, explSet);\n processed.push(...slice);\n continue;\n case \"both\":\n reparseMacroNames(slice, bothSet);\n processed.push(...slice);\n continue;\n default:\n throw new Error(\n `Unexpected case when splitting ${key}`\n );\n }\n }\n\n nodes.length = 0;\n nodes.push(...processed);\n return SKIP;\n },\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n"],"names":["match","visit","EXIT","SKIP"],"mappings":"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"}
package/index.d.ts CHANGED
@@ -1,14 +1,60 @@
1
- export * from "./libs/find-region";
2
- export * from "./libs/special-regions";
3
- export * from "./libs/reparse-macro-names";
4
- /**
5
- * ## What is this?
6
- *
7
- * Functions to identify regions of a `unified-latex` Abstract Syntax Tree (AST) that need to be reparsed because of different
8
- * category codes. For example, regions between `\makeatletter` and `\makeatother`.
9
- *
10
- * ## When should I use this?
11
- *
12
- * If you need to identify regions of the AST that need to be reparsed.
13
- */
14
- //# sourceMappingURL=index.d.ts.map
1
+ import * as Ast from '@unified-latex/unified-latex-types';
2
+
3
+ /**
4
+ * Find regions between `\ExplSyntaxOn...\ExplSyntaxOff` and `\makeatletter...\makeatother`.
5
+ * Returns an object containing regions where one or both syntax's apply.
6
+ */
7
+ export declare function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {
8
+ explOnly: Region[];
9
+ atLetterOnly: Region[];
10
+ both: Region[];
11
+ };
12
+
13
+ /**
14
+ * Find all contiguous segments in the array that are between start and end blocks.
15
+ * The `start` and `end` are functions that determine when a region starts and ends.
16
+ */
17
+ export declare function findRegionInArray(tree: Ast.Node[], start: (node: Ast.Node) => boolean, end: (node: Ast.Node) => boolean): Region[];
18
+
19
+ /**
20
+ * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but
21
+ * do not do any reparsing. This function can be used in auto-detection schemes to determine if
22
+ * macro names should actually be reparsed.
23
+ */
24
+ export declare function hasReparsableMacroNames(tree: Ast.Ast, allowedTokens: string | Set<string>): boolean;
25
+
26
+ /**
27
+ * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but
28
+ * do not do any reparsing. This function can be used in auto-detection schemes to determine if
29
+ * macro names should actually be reparsed.
30
+ */
31
+ export declare function hasReparsableMacroNamesInArray(tree: Ast.Node[], allowedTokens: Set<string>): boolean;
32
+
33
+ declare type Region = {
34
+ start: number;
35
+ end: number;
36
+ };
37
+
38
+ /**
39
+ * Find regions between `\ExplSyntaxOn...\ExplSyntaxOff` and `\makeatletter...\makeatother`
40
+ * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become
41
+ * part of the macro names.
42
+ */
43
+ export declare function reparseExpl3AndAtLetterRegions(tree: Ast.Ast): void;
44
+
45
+ /**
46
+ * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.
47
+ * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though
48
+ * `_` is normally stops the parsing for a macro name). Thus, a macro `\foo_bar:Nn` would be parsed as having
49
+ * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.
50
+ */
51
+ export declare function reparseMacroNames(tree: Ast.Ast, allowedTokens: string | Set<string>): void;
52
+
53
+ /**
54
+ * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.
55
+ * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though
56
+ * `_` is normally stops the parsing for a macro name).
57
+ */
58
+ export declare function reparseMacroNamesInArray(tree: Ast.Node[], allowedTokens: Set<string>): void;
59
+
60
+ export { }
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
- // libs/find-region.ts
1
+ import { match } from "@unified-latex/unified-latex-util-match";
2
+ import { visit, EXIT, SKIP } from "@unified-latex/unified-latex-util-visit";
2
3
  function findRegionInArray(tree, start, end) {
3
4
  const ret = [];
4
5
  let currRegion = { start: void 0, end: tree.length };
@@ -18,11 +19,6 @@ function findRegionInArray(tree, start, end) {
18
19
  }
19
20
  return ret;
20
21
  }
21
-
22
- // libs/special-regions.ts
23
- import { match as match2 } from "@unified-latex/unified-latex-util-match";
24
-
25
- // libs/regions.ts
26
22
  function refineRegions(regions) {
27
23
  const _regions = [...regions];
28
24
  _regions.sort((a, b) => a.start - b.start);
@@ -86,13 +82,6 @@ function splitByRegions(array, regionsRecord) {
86
82
  }
87
83
  return ret;
88
84
  }
89
-
90
- // libs/special-regions.ts
91
- import { SKIP, visit as visit2 } from "@unified-latex/unified-latex-util-visit";
92
-
93
- // libs/reparse-macro-names.ts
94
- import { match } from "@unified-latex/unified-latex-util-match";
95
- import { EXIT, visit } from "@unified-latex/unified-latex-util-visit";
96
85
  function escapeRegExp(str) {
97
86
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
98
87
  }
@@ -153,8 +142,8 @@ function reparseMacroNamesInArray(tree, allowedTokens) {
153
142
  (allowedTokens.has(
154
143
  macro.content.charAt(macro.content.length - 1)
155
144
  ) || allowedTokens.has(string.content.charAt(0)))) {
156
- const match3 = string.content.match(regex);
157
- const takeable = match3 ? match3[0] : "";
145
+ const match2 = string.content.match(regex);
146
+ const takeable = match2 ? match2[0] : "";
158
147
  if (takeable.length > 0) {
159
148
  if (takeable.length === string.content.length) {
160
149
  macro.content += string.content;
@@ -202,15 +191,13 @@ function reparseMacroNames(tree, allowedTokens) {
202
191
  { includeArrays: true, test: Array.isArray }
203
192
  );
204
193
  }
205
-
206
- // libs/special-regions.ts
207
- var expl3Find = {
208
- start: match2.createMacroMatcher(["ExplSyntaxOn"]),
209
- end: match2.createMacroMatcher(["ExplSyntaxOff"])
194
+ const expl3Find = {
195
+ start: match.createMacroMatcher(["ExplSyntaxOn"]),
196
+ end: match.createMacroMatcher(["ExplSyntaxOff"])
210
197
  };
211
- var atLetterFind = {
212
- start: match2.createMacroMatcher(["makeatletter"]),
213
- end: match2.createMacroMatcher(["makeatother"])
198
+ const atLetterFind = {
199
+ start: match.createMacroMatcher(["makeatletter"]),
200
+ end: match.createMacroMatcher(["makeatother"])
214
201
  };
215
202
  function findExpl3AndAtLetterRegionsInArray(tree) {
216
203
  const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);
@@ -250,11 +237,11 @@ function findExpl3AndAtLetterRegionsInArray(tree) {
250
237
  ret.both = ret.both.filter((r) => r.end - r.start > 1);
251
238
  return ret;
252
239
  }
253
- var atLetterSet = /* @__PURE__ */ new Set(["@"]);
254
- var explSet = /* @__PURE__ */ new Set(["_", ":"]);
255
- var bothSet = /* @__PURE__ */ new Set(["_", ":", "@"]);
240
+ const atLetterSet = /* @__PURE__ */ new Set(["@"]);
241
+ const explSet = /* @__PURE__ */ new Set(["_", ":"]);
242
+ const bothSet = /* @__PURE__ */ new Set(["_", ":", "@"]);
256
243
  function reparseExpl3AndAtLetterRegions(tree) {
257
- visit2(
244
+ visit(
258
245
  tree,
259
246
  {
260
247
  leave: (nodes) => {
package/index.js.map CHANGED
@@ -1,7 +1 @@
1
- {
2
- "version": 3,
3
- "sources": ["../libs/find-region.ts", "../libs/special-regions.ts", "../libs/regions.ts", "../libs/reparse-macro-names.ts"],
4
- "sourcesContent": ["import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { Region } from \"./regions\";\n\n/**\n * Find all contiguous segments in the array that are between start and end blocks.\n * The `start` and `end` are functions that determine when a region starts and ends.\n */\nexport function findRegionInArray(\n tree: Ast.Node[],\n start: (node: Ast.Node) => boolean,\n end: (node: Ast.Node) => boolean\n): Region[] {\n const ret: Region[] = [];\n let currRegion: Region = { start: undefined as any, end: tree.length };\n for (let i = 0; i < tree.length; i++) {\n const node = tree[i];\n if (start(node)) {\n currRegion.start = i;\n }\n if (end(node)) {\n currRegion.end = i + 1;\n ret.push(currRegion);\n currRegion = { start: undefined as any, end: tree.length };\n }\n }\n\n if (currRegion.start != null) {\n // Regions don't necessarily have to encounter an `end` to end.\n ret.push(currRegion);\n }\n return ret;\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { findRegionInArray } from \"./find-region\";\nimport { refineRegions, Region, splitByRegions } from \"./regions\";\nimport { SKIP, visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { reparseMacroNames } from \"./reparse-macro-names\";\n\nconst expl3Find = {\n start: match.createMacroMatcher([\"ExplSyntaxOn\"]),\n end: match.createMacroMatcher([\"ExplSyntaxOff\"]),\n};\nconst atLetterFind = {\n start: match.createMacroMatcher([\"makeatletter\"]),\n end: match.createMacroMatcher([\"makeatother\"]),\n};\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`.\n * Returns an object containing regions where one or both syntax's apply.\n */\nexport function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {\n explOnly: Region[];\n atLetterOnly: Region[];\n both: Region[];\n} {\n const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);\n const atLetter = findRegionInArray(\n tree,\n atLetterFind.start,\n atLetterFind.end\n );\n\n const regionMap = new Map([\n ...(expl3.map((x) => [x, \"expl\"]) as [Region, \"expl\"][]),\n ...(atLetter.map((x) => [x, \"atLetter\"]) as [Region, \"atLetter\"][]),\n ]);\n const all = refineRegions([...expl3, ...atLetter]);\n\n const ret = {\n explOnly: [] as Region[],\n atLetterOnly: [] as Region[],\n both: [] as Region[],\n };\n\n for (let i = 0; i < all.regions.length; i++) {\n const region = all.regions[i];\n const containedIn = all.regionsContainedIn[i];\n if (containedIn.size === 2) {\n ret.both.push(region);\n continue;\n }\n for (const v of containedIn.values()) {\n if (regionMap.get(v) === \"expl\") {\n ret.explOnly.push(region);\n }\n if (regionMap.get(v) === \"atLetter\") {\n ret.atLetterOnly.push(region);\n }\n }\n }\n\n // Regions of size 1 only contain the starting/stopping macro, so they should be discarded\n ret.explOnly = ret.explOnly.filter((r) => r.end - r.start > 1);\n ret.atLetterOnly = ret.atLetterOnly.filter((r) => r.end - r.start > 1);\n ret.both = ret.both.filter((r) => r.end - r.start > 1);\n\n return ret;\n}\n\nconst atLetterSet = new Set([\"@\"]);\nconst explSet = new Set([\"_\", \":\"]);\nconst bothSet = new Set([\"_\", \":\", \"@\"]);\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`\n * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become\n * part of the macro names.\n */\nexport function reparseExpl3AndAtLetterRegions(tree: Ast.Ast) {\n visit(\n tree,\n {\n leave: (nodes) => {\n const regions = findExpl3AndAtLetterRegionsInArray(nodes);\n // In all likelihood, we don't need to do any reparsing, so bail early here\n const totalNumRegions =\n regions.both.length +\n regions.atLetterOnly.length +\n regions.explOnly.length;\n if (totalNumRegions === 0) {\n return;\n }\n\n const splits = splitByRegions(nodes, regions);\n const processed: typeof nodes = [];\n for (const [key, slice] of splits) {\n switch (key) {\n case null:\n processed.push(...slice);\n continue;\n case \"atLetterOnly\":\n reparseMacroNames(slice, atLetterSet);\n processed.push(...slice);\n continue;\n case \"explOnly\":\n reparseMacroNames(slice, explSet);\n processed.push(...slice);\n continue;\n case \"both\":\n reparseMacroNames(slice, bothSet);\n processed.push(...slice);\n continue;\n default:\n throw new Error(\n `Unexpected case when splitting ${key}`\n );\n }\n }\n\n nodes.length = 0;\n nodes.push(...processed);\n return SKIP;\n },\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\n\nexport type Region = { start: number; end: number };\n\n/**\n * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,\n * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region\n * is a subset of.\n */\nexport function refineRegions(regions: Region[]): {\n regions: Region[];\n regionsContainedIn: Set<Region>[];\n} {\n const _regions = [...regions];\n _regions.sort((a, b) => a.start - b.start);\n const cutPointsSet = new Set(_regions.flatMap((r) => [r.start, r.end]));\n const cutPoints = Array.from(cutPointsSet);\n cutPoints.sort((a, b) => a - b);\n\n const retRegions: Region[] = [];\n const retRegionsContainedIn: Set<Region>[] = [];\n\n // We will be checking what regions we are completely contained in.\n // Because `_regions` is sorted by start, `seekIndex` will be incremented\n // by end, so that we don't do too much array testing.\n let seekIndex = 0;\n for (let i = 0; i < cutPoints.length - 1; i++) {\n const start = cutPoints[i];\n const end = cutPoints[i + 1];\n const region = { start, end };\n const regionContainedIn: Set<Region> = new Set();\n\n let encounteredEndPastStart = false;\n for (let j = seekIndex; j < _regions.length; j++) {\n const superRegion = _regions[j];\n if (superRegion.end >= region.start) {\n encounteredEndPastStart = true;\n }\n if (!encounteredEndPastStart && superRegion.end < region.start) {\n // In this case, the region (and all regions that came before)\n // end before the region we are testing, so we may safely skip past it\n // from here on out.\n seekIndex = j + 1;\n continue;\n }\n\n if (superRegion.start > end) {\n // Because `_regions` is sorted, we can stop here\n break;\n }\n if (\n superRegion.start <= region.start &&\n superRegion.end >= region.end\n ) {\n encounteredEndPastStart = true;\n regionContainedIn.add(superRegion);\n }\n }\n\n if (regionContainedIn.size > 0) {\n // We only count if we are contained in a subregion\n retRegions.push(region);\n retRegionsContainedIn.push(regionContainedIn);\n }\n }\n\n return { regions: retRegions, regionsContainedIn: retRegionsContainedIn };\n}\n\n/**\n * Split an array up into the disjoint regions specified by `regionRecord`.\n * Returned is a list of tuples, the first item being the key of `regionRecord` if there\n * was a corresponding region, or `null` if there was no corresponding region.\n *\n * This function assumes that the regions in `regionRecord` are disjoint and fully contained\n * within the bounds of `array`.\n */\nexport function splitByRegions<\n T,\n RegionRecord extends Record<string, Region[]>,\n>(array: T[], regionsRecord: RegionRecord) {\n const ret: [keyof RegionRecord | null, T[]][] = [];\n\n const indices = [0, array.length];\n const reverseMap: Record<string, keyof RegionRecord> = {};\n for (const [key, records] of Object.entries(regionsRecord)) {\n indices.push(\n ...records.flatMap((r) => {\n reverseMap[\"\" + [r.start, r.end]] = key;\n return [r.start, r.end];\n })\n );\n }\n indices.sort((a, b) => a - b);\n\n for (let i = 0; i < indices.length - 1; i++) {\n const start = indices[i];\n const end = indices[i + 1];\n if (start === end) {\n continue;\n }\n const regionKey = reverseMap[\"\" + [start, end]];\n\n ret.push([regionKey || null, array.slice(start, end)]);\n }\n\n return ret;\n}\n", "import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { EXIT, visit } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Escape a string so that it can be used to build a regular expression.\n *\n * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nfunction escapeRegExp(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\n/**\n * Build a regular expression that matches everything up to the first non-allowed symbol.\n */\nfunction buildWordRegex(allowedSet: Set<string>): RegExp {\n // /\\p{L}/ matches all letters, including unicode letters. We join this with\n // everything allowed in our set to form a regexp like\n // /(\\p{L}|_|:)*/u\n // The `u` at the end allows unicode characters to be matched.\n const regexpStr = `^(${[\"\\\\p{L}\"]\n .concat(Array.from(allowedSet).map(escapeRegExp))\n .join(\"|\")})*`;\n return new RegExp(regexpStr, \"u\");\n}\n\n/**\n * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n): boolean {\n for (let i = 0; i < tree.length; i++) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (match.anyMacro(macro) && match.anyString(string)) {\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n if (\n allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n): boolean {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n let ret = false;\n visit(\n tree,\n (nodes) => {\n if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {\n ret = true;\n return EXIT;\n }\n },\n { includeArrays: true, test: Array.isArray }\n );\n return ret;\n}\n\n/**\n * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name).\n */\nexport function reparseMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n) {\n const regex = buildWordRegex(allowedTokens);\n let i = 0;\n while (i < tree.length) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (\n match.anyMacro(macro) &&\n // The _^ macros in math mode should not be extended no-matter what;\n // So we check to make sure that the macro we're dealing with has the default escape token.\n (macro.escapeToken == null || macro.escapeToken === \"\\\\\") &&\n match.anyString(string) &&\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n (allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0)))\n ) {\n // There might be a number somewhere in the string. If so, we should\n // break the string apart at that number\n const match = string.content.match(regex);\n const takeable = match ? match[0] : \"\";\n if (takeable.length > 0) {\n if (takeable.length === string.content.length) {\n // The whole string can be appended to the macro name\n macro.content += string.content;\n tree.splice(i + 1, 1);\n\n // Preserve the source location if available\n if (macro.position && string.position?.end) {\n macro.position.end = string.position.end;\n }\n } else {\n // Only part of the string can be appended to the macro name\n macro.content += takeable;\n string.content = string.content.slice(takeable.length);\n\n // Preserve the source location if available\n if (macro.position?.end) {\n macro.position.end.offset += takeable.length;\n macro.position.end.column += takeable.length;\n }\n if (string.position?.start) {\n string.position.start.offset += takeable.length;\n string.position.start.column += takeable.length;\n }\n }\n } else {\n i++;\n }\n } else {\n ++i;\n }\n }\n}\n\n/**\n * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name). Thus, a macro `\\foo_bar:Nn` would be parsed as having\n * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.\n */\nexport function reparseMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n) {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n visit(\n tree,\n (nodes) => {\n reparseMacroNamesInArray(nodes, _allowedTokens);\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n"],
5
- "mappings": "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",
6
- "names": ["match", "visit", "match", "match", "visit"]
7
- }
1
+ {"version":3,"file":"index.js","sources":["../libs/find-region.ts","../libs/regions.ts","../libs/reparse-macro-names.ts","../libs/special-regions.ts"],"sourcesContent":["import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { Region } from \"./regions\";\n\n/**\n * Find all contiguous segments in the array that are between start and end blocks.\n * The `start` and `end` are functions that determine when a region starts and ends.\n */\nexport function findRegionInArray(\n tree: Ast.Node[],\n start: (node: Ast.Node) => boolean,\n end: (node: Ast.Node) => boolean\n): Region[] {\n const ret: Region[] = [];\n let currRegion: Region = { start: undefined as any, end: tree.length };\n for (let i = 0; i < tree.length; i++) {\n const node = tree[i];\n if (start(node)) {\n currRegion.start = i;\n }\n if (end(node)) {\n currRegion.end = i + 1;\n ret.push(currRegion);\n currRegion = { start: undefined as any, end: tree.length };\n }\n }\n\n if (currRegion.start != null) {\n // Regions don't necessarily have to encounter an `end` to end.\n ret.push(currRegion);\n }\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\n\nexport type Region = { start: number; end: number };\n\n/**\n * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,\n * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region\n * is a subset of.\n */\nexport function refineRegions(regions: Region[]): {\n regions: Region[];\n regionsContainedIn: Set<Region>[];\n} {\n const _regions = [...regions];\n _regions.sort((a, b) => a.start - b.start);\n const cutPointsSet = new Set(_regions.flatMap((r) => [r.start, r.end]));\n const cutPoints = Array.from(cutPointsSet);\n cutPoints.sort((a, b) => a - b);\n\n const retRegions: Region[] = [];\n const retRegionsContainedIn: Set<Region>[] = [];\n\n // We will be checking what regions we are completely contained in.\n // Because `_regions` is sorted by start, `seekIndex` will be incremented\n // by end, so that we don't do too much array testing.\n let seekIndex = 0;\n for (let i = 0; i < cutPoints.length - 1; i++) {\n const start = cutPoints[i];\n const end = cutPoints[i + 1];\n const region = { start, end };\n const regionContainedIn: Set<Region> = new Set();\n\n let encounteredEndPastStart = false;\n for (let j = seekIndex; j < _regions.length; j++) {\n const superRegion = _regions[j];\n if (superRegion.end >= region.start) {\n encounteredEndPastStart = true;\n }\n if (!encounteredEndPastStart && superRegion.end < region.start) {\n // In this case, the region (and all regions that came before)\n // end before the region we are testing, so we may safely skip past it\n // from here on out.\n seekIndex = j + 1;\n continue;\n }\n\n if (superRegion.start > end) {\n // Because `_regions` is sorted, we can stop here\n break;\n }\n if (\n superRegion.start <= region.start &&\n superRegion.end >= region.end\n ) {\n encounteredEndPastStart = true;\n regionContainedIn.add(superRegion);\n }\n }\n\n if (regionContainedIn.size > 0) {\n // We only count if we are contained in a subregion\n retRegions.push(region);\n retRegionsContainedIn.push(regionContainedIn);\n }\n }\n\n return { regions: retRegions, regionsContainedIn: retRegionsContainedIn };\n}\n\n/**\n * Split an array up into the disjoint regions specified by `regionRecord`.\n * Returned is a list of tuples, the first item being the key of `regionRecord` if there\n * was a corresponding region, or `null` if there was no corresponding region.\n *\n * This function assumes that the regions in `regionRecord` are disjoint and fully contained\n * within the bounds of `array`.\n */\nexport function splitByRegions<\n T,\n RegionRecord extends Record<string, Region[]>\n>(array: T[], regionsRecord: RegionRecord) {\n const ret: [keyof RegionRecord | null, T[]][] = [];\n\n const indices = [0, array.length];\n const reverseMap: Record<string, keyof RegionRecord> = {};\n for (const [key, records] of Object.entries(regionsRecord)) {\n indices.push(\n ...records.flatMap((r) => {\n reverseMap[\"\" + [r.start, r.end]] = key;\n return [r.start, r.end];\n })\n );\n }\n indices.sort((a, b) => a - b);\n\n for (let i = 0; i < indices.length - 1; i++) {\n const start = indices[i];\n const end = indices[i + 1];\n if (start === end) {\n continue;\n }\n const regionKey = reverseMap[\"\" + [start, end]];\n\n ret.push([regionKey || null, array.slice(start, end)]);\n }\n\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { EXIT, visit } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Escape a string so that it can be used to build a regular expression.\n *\n * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nfunction escapeRegExp(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\n/**\n * Build a regular expression that matches everything up to the first non-allowed symbol.\n */\nfunction buildWordRegex(allowedSet: Set<string>): RegExp {\n // /\\p{L}/ matches all letters, including unicode letters. We join this with\n // everything allowed in our set to form a regexp like\n // /(\\p{L}|_|:)*/u\n // The `u` at the end allows unicode characters to be matched.\n const regexpStr = `^(${[\"\\\\p{L}\"]\n .concat(Array.from(allowedSet).map(escapeRegExp))\n .join(\"|\")})*`;\n return new RegExp(regexpStr, \"u\");\n}\n\n/**\n * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n): boolean {\n for (let i = 0; i < tree.length; i++) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (match.anyMacro(macro) && match.anyString(string)) {\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n if (\n allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n): boolean {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n let ret = false;\n visit(\n tree,\n (nodes) => {\n if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {\n ret = true;\n return EXIT;\n }\n },\n { includeArrays: true, test: Array.isArray }\n );\n return ret;\n}\n\n/**\n * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name).\n */\nexport function reparseMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n) {\n const regex = buildWordRegex(allowedTokens);\n let i = 0;\n while (i < tree.length) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (\n match.anyMacro(macro) &&\n // The _^ macros in math mode should not be extended no-matter what;\n // So we check to make sure that the macro we're dealing with has the default escape token.\n (macro.escapeToken == null || macro.escapeToken === \"\\\\\") &&\n match.anyString(string) &&\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n (allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0)))\n ) {\n // There might be a number somewhere in the string. If so, we should\n // break the string apart at that number\n const match = string.content.match(regex);\n const takeable = match ? match[0] : \"\";\n if (takeable.length > 0) {\n if (takeable.length === string.content.length) {\n // The whole string can be appended to the macro name\n macro.content += string.content;\n tree.splice(i + 1, 1);\n\n // Preserve the source location if available\n if (macro.position && string.position?.end) {\n macro.position.end = string.position.end;\n }\n } else {\n // Only part of the string can be appended to the macro name\n macro.content += takeable;\n string.content = string.content.slice(takeable.length);\n\n // Preserve the source location if available\n if (macro.position?.end) {\n macro.position.end.offset += takeable.length;\n macro.position.end.column += takeable.length;\n }\n if (string.position?.start) {\n string.position.start.offset += takeable.length;\n string.position.start.column += takeable.length;\n }\n }\n } else {\n i++;\n }\n } else {\n ++i;\n }\n }\n}\n\n/**\n * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name). Thus, a macro `\\foo_bar:Nn` would be parsed as having\n * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.\n */\nexport function reparseMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n) {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n visit(\n tree,\n (nodes) => {\n reparseMacroNamesInArray(nodes, _allowedTokens);\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { findRegionInArray } from \"./find-region\";\nimport { refineRegions, Region, splitByRegions } from \"./regions\";\nimport { SKIP, visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { reparseMacroNames } from \"./reparse-macro-names\";\n\nconst expl3Find = {\n start: match.createMacroMatcher([\"ExplSyntaxOn\"]),\n end: match.createMacroMatcher([\"ExplSyntaxOff\"]),\n};\nconst atLetterFind = {\n start: match.createMacroMatcher([\"makeatletter\"]),\n end: match.createMacroMatcher([\"makeatother\"]),\n};\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`.\n * Returns an object containing regions where one or both syntax's apply.\n */\nexport function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {\n explOnly: Region[];\n atLetterOnly: Region[];\n both: Region[];\n} {\n const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);\n const atLetter = findRegionInArray(\n tree,\n atLetterFind.start,\n atLetterFind.end\n );\n\n const regionMap = new Map([\n ...(expl3.map((x) => [x, \"expl\"]) as [Region, \"expl\"][]),\n ...(atLetter.map((x) => [x, \"atLetter\"]) as [Region, \"atLetter\"][]),\n ]);\n const all = refineRegions([...expl3, ...atLetter]);\n\n const ret = {\n explOnly: [] as Region[],\n atLetterOnly: [] as Region[],\n both: [] as Region[],\n };\n\n for (let i = 0; i < all.regions.length; i++) {\n const region = all.regions[i];\n const containedIn = all.regionsContainedIn[i];\n if (containedIn.size === 2) {\n ret.both.push(region);\n continue;\n }\n for (const v of containedIn.values()) {\n if (regionMap.get(v) === \"expl\") {\n ret.explOnly.push(region);\n }\n if (regionMap.get(v) === \"atLetter\") {\n ret.atLetterOnly.push(region);\n }\n }\n }\n\n // Regions of size 1 only contain the starting/stopping macro, so they should be discarded\n ret.explOnly = ret.explOnly.filter((r) => r.end - r.start > 1);\n ret.atLetterOnly = ret.atLetterOnly.filter((r) => r.end - r.start > 1);\n ret.both = ret.both.filter((r) => r.end - r.start > 1);\n\n return ret;\n}\n\nconst atLetterSet = new Set([\"@\"]);\nconst explSet = new Set([\"_\", \":\"]);\nconst bothSet = new Set([\"_\", \":\", \"@\"]);\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`\n * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become\n * part of the macro names.\n */\nexport function reparseExpl3AndAtLetterRegions(tree: Ast.Ast) {\n visit(\n tree,\n {\n leave: (nodes) => {\n const regions = findExpl3AndAtLetterRegionsInArray(nodes);\n // In all likelihood, we don't need to do any reparsing, so bail early here\n const totalNumRegions =\n regions.both.length +\n regions.atLetterOnly.length +\n regions.explOnly.length;\n if (totalNumRegions === 0) {\n return;\n }\n\n const splits = splitByRegions(nodes, regions);\n const processed: typeof nodes = [];\n for (const [key, slice] of splits) {\n switch (key) {\n case null:\n processed.push(...slice);\n continue;\n case \"atLetterOnly\":\n reparseMacroNames(slice, atLetterSet);\n processed.push(...slice);\n continue;\n case \"explOnly\":\n reparseMacroNames(slice, explSet);\n processed.push(...slice);\n continue;\n case \"both\":\n reparseMacroNames(slice, bothSet);\n processed.push(...slice);\n continue;\n default:\n throw new Error(\n `Unexpected case when splitting ${key}`\n );\n }\n }\n\n nodes.length = 0;\n nodes.push(...processed);\n return SKIP;\n },\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n"],"names":["match"],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@unified-latex/unified-latex-util-catcode",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Tools for manipulating unified-latex ASTs",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "dependencies": {
8
- "@unified-latex/unified-latex-types": "^1.6.0",
9
- "@unified-latex/unified-latex-util-match": "^1.6.0",
10
- "@unified-latex/unified-latex-util-visit": "^1.6.0"
8
+ "@unified-latex/unified-latex-types": "^1.7.0",
9
+ "@unified-latex/unified-latex-util-match": "^1.7.0",
10
+ "@unified-latex/unified-latex-util-visit": "^1.7.0"
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",
package/index.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAG3C;;;;;;;;;GASG"}
@@ -1,8 +0,0 @@
1
- import * as Ast from "@unified-latex/unified-latex-types";
2
- import { Region } from "./regions";
3
- /**
4
- * Find all contiguous segments in the array that are between start and end blocks.
5
- * The `start` and `end` are functions that determine when a region starts and ends.
6
- */
7
- export declare function findRegionInArray(tree: Ast.Node[], start: (node: Ast.Node) => boolean, end: (node: Ast.Node) => boolean): Region[];
8
- //# sourceMappingURL=find-region.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"find-region.d.ts","sourceRoot":"","sources":["../../libs/find-region.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,oCAAoC,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAChB,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,OAAO,EAClC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,OAAO,GACjC,MAAM,EAAE,CAoBV"}
package/libs/regions.d.ts DELETED
@@ -1,23 +0,0 @@
1
- export type Region = {
2
- start: number;
3
- end: number;
4
- };
5
- /**
6
- * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,
7
- * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region
8
- * is a subset of.
9
- */
10
- export declare function refineRegions(regions: Region[]): {
11
- regions: Region[];
12
- regionsContainedIn: Set<Region>[];
13
- };
14
- /**
15
- * Split an array up into the disjoint regions specified by `regionRecord`.
16
- * Returned is a list of tuples, the first item being the key of `regionRecord` if there
17
- * was a corresponding region, or `null` if there was no corresponding region.
18
- *
19
- * This function assumes that the regions in `regionRecord` are disjoint and fully contained
20
- * within the bounds of `array`.
21
- */
22
- export declare function splitByRegions<T, RegionRecord extends Record<string, Region[]>>(array: T[], regionsRecord: RegionRecord): [keyof RegionRecord | null, T[]][];
23
- //# sourceMappingURL=regions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"regions.d.ts","sourceRoot":"","sources":["../../libs/regions.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;IAC9C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;CACrC,CAuDA;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC1B,CAAC,EACD,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAC/C,KAAK,EAAE,CAAC,EAAE,EAAE,aAAa,EAAE,YAAY,sCA2BxC"}
@@ -1,27 +0,0 @@
1
- import * as Ast from "@unified-latex/unified-latex-types";
2
- /**
3
- * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but
4
- * do not do any reparsing. This function can be used in auto-detection schemes to determine if
5
- * macro names should actually be reparsed.
6
- */
7
- export declare function hasReparsableMacroNamesInArray(tree: Ast.Node[], allowedTokens: Set<string>): boolean;
8
- /**
9
- * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but
10
- * do not do any reparsing. This function can be used in auto-detection schemes to determine if
11
- * macro names should actually be reparsed.
12
- */
13
- export declare function hasReparsableMacroNames(tree: Ast.Ast, allowedTokens: string | Set<string>): boolean;
14
- /**
15
- * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.
16
- * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though
17
- * `_` is normally stops the parsing for a macro name).
18
- */
19
- export declare function reparseMacroNamesInArray(tree: Ast.Node[], allowedTokens: Set<string>): void;
20
- /**
21
- * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.
22
- * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though
23
- * `_` is normally stops the parsing for a macro name). Thus, a macro `\foo_bar:Nn` would be parsed as having
24
- * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.
25
- */
26
- export declare function reparseMacroNames(tree: Ast.Ast, allowedTokens: string | Set<string>): void;
27
- //# sourceMappingURL=reparse-macro-names.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reparse-macro-names.d.ts","sourceRoot":"","sources":["../../libs/reparse-macro-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,oCAAoC,CAAC;AA2B1D;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC1C,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAChB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAC3B,OAAO,CAkBT;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACnC,IAAI,EAAE,GAAG,CAAC,GAAG,EACb,aAAa,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,GACpC,OAAO,CA0BT;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACpC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAChB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,QAwD7B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC7B,IAAI,EAAE,GAAG,CAAC,GAAG,EACb,aAAa,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,QAsBtC"}
@@ -1,18 +0,0 @@
1
- import * as Ast from "@unified-latex/unified-latex-types";
2
- import { Region } from "./regions";
3
- /**
4
- * Find regions between `\ExplSyntaxOn...\ExplSyntaxOff` and `\makeatletter...\makeatother`.
5
- * Returns an object containing regions where one or both syntax's apply.
6
- */
7
- export declare function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {
8
- explOnly: Region[];
9
- atLetterOnly: Region[];
10
- both: Region[];
11
- };
12
- /**
13
- * Find regions between `\ExplSyntaxOn...\ExplSyntaxOff` and `\makeatletter...\makeatother`
14
- * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become
15
- * part of the macro names.
16
- */
17
- export declare function reparseExpl3AndAtLetterRegions(tree: Ast.Ast): void;
18
- //# sourceMappingURL=special-regions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"special-regions.d.ts","sourceRoot":"","sources":["../../libs/special-regions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,oCAAoC,CAAC;AAG1D,OAAO,EAAiB,MAAM,EAAkB,MAAM,WAAW,CAAC;AAalE;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG;IAClE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;CAClB,CA2CA;AAMD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,QAgD3D"}