@m4ike1/ion-tui 0.1.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.
Files changed (196) hide show
  1. package/README.md +114 -0
  2. package/dist/alt-screen-search.d.ts +46 -0
  3. package/dist/alt-screen-search.d.ts.map +1 -0
  4. package/dist/alt-screen-search.js +282 -0
  5. package/dist/alt-screen-search.js.map +1 -0
  6. package/dist/autocomplete.d.ts +75 -0
  7. package/dist/autocomplete.d.ts.map +1 -0
  8. package/dist/autocomplete.js +749 -0
  9. package/dist/autocomplete.js.map +1 -0
  10. package/dist/components/alt-screen-flash.d.ts +13 -0
  11. package/dist/components/alt-screen-flash.d.ts.map +1 -0
  12. package/dist/components/alt-screen-flash.js +37 -0
  13. package/dist/components/alt-screen-flash.js.map +1 -0
  14. package/dist/components/box.d.ts +24 -0
  15. package/dist/components/box.d.ts.map +1 -0
  16. package/dist/components/box.js +133 -0
  17. package/dist/components/box.js.map +1 -0
  18. package/dist/components/cancellable-loader.d.ts +22 -0
  19. package/dist/components/cancellable-loader.d.ts.map +1 -0
  20. package/dist/components/cancellable-loader.js +35 -0
  21. package/dist/components/cancellable-loader.js.map +1 -0
  22. package/dist/components/editor.d.ts +266 -0
  23. package/dist/components/editor.d.ts.map +1 -0
  24. package/dist/components/editor.js +2087 -0
  25. package/dist/components/editor.js.map +1 -0
  26. package/dist/components/h-stack.d.ts +7 -0
  27. package/dist/components/h-stack.d.ts.map +1 -0
  28. package/dist/components/h-stack.js +43 -0
  29. package/dist/components/h-stack.js.map +1 -0
  30. package/dist/components/image.d.ts +28 -0
  31. package/dist/components/image.d.ts.map +1 -0
  32. package/dist/components/image.js +90 -0
  33. package/dist/components/image.js.map +1 -0
  34. package/dist/components/input.d.ts +48 -0
  35. package/dist/components/input.d.ts.map +1 -0
  36. package/dist/components/input.js +417 -0
  37. package/dist/components/input.js.map +1 -0
  38. package/dist/components/loader.d.ts +33 -0
  39. package/dist/components/loader.d.ts.map +1 -0
  40. package/dist/components/loader.js +76 -0
  41. package/dist/components/loader.js.map +1 -0
  42. package/dist/components/markdown.d.ts +103 -0
  43. package/dist/components/markdown.d.ts.map +1 -0
  44. package/dist/components/markdown.js +858 -0
  45. package/dist/components/markdown.js.map +1 -0
  46. package/dist/components/mouse-region.d.ts +12 -0
  47. package/dist/components/mouse-region.d.ts.map +1 -0
  48. package/dist/components/mouse-region.js +21 -0
  49. package/dist/components/mouse-region.js.map +1 -0
  50. package/dist/components/scroll-view.d.ts +68 -0
  51. package/dist/components/scroll-view.d.ts.map +1 -0
  52. package/dist/components/scroll-view.js +199 -0
  53. package/dist/components/scroll-view.js.map +1 -0
  54. package/dist/components/select-list.d.ts +53 -0
  55. package/dist/components/select-list.d.ts.map +1 -0
  56. package/dist/components/select-list.js +206 -0
  57. package/dist/components/select-list.js.map +1 -0
  58. package/dist/components/settings-list.d.ts +60 -0
  59. package/dist/components/settings-list.d.ts.map +1 -0
  60. package/dist/components/settings-list.js +252 -0
  61. package/dist/components/settings-list.js.map +1 -0
  62. package/dist/components/spacer.d.ts +12 -0
  63. package/dist/components/spacer.d.ts.map +1 -0
  64. package/dist/components/spacer.js +23 -0
  65. package/dist/components/spacer.js.map +1 -0
  66. package/dist/components/stack.d.ts +32 -0
  67. package/dist/components/stack.d.ts.map +1 -0
  68. package/dist/components/stack.js +111 -0
  69. package/dist/components/stack.js.map +1 -0
  70. package/dist/components/text.d.ts +19 -0
  71. package/dist/components/text.d.ts.map +1 -0
  72. package/dist/components/text.js +90 -0
  73. package/dist/components/text.js.map +1 -0
  74. package/dist/components/truncated-text.d.ts +13 -0
  75. package/dist/components/truncated-text.d.ts.map +1 -0
  76. package/dist/components/truncated-text.js +51 -0
  77. package/dist/components/truncated-text.js.map +1 -0
  78. package/dist/components/v-stack.d.ts +8 -0
  79. package/dist/components/v-stack.d.ts.map +1 -0
  80. package/dist/components/v-stack.js +26 -0
  81. package/dist/components/v-stack.js.map +1 -0
  82. package/dist/components/virtual-list.d.ts +51 -0
  83. package/dist/components/virtual-list.d.ts.map +1 -0
  84. package/dist/components/virtual-list.js +170 -0
  85. package/dist/components/virtual-list.js.map +1 -0
  86. package/dist/editor-component.d.ts +39 -0
  87. package/dist/editor-component.d.ts.map +1 -0
  88. package/dist/editor-component.js +2 -0
  89. package/dist/editor-component.js.map +1 -0
  90. package/dist/fuzzy.d.ts +16 -0
  91. package/dist/fuzzy.d.ts.map +1 -0
  92. package/dist/fuzzy.js +110 -0
  93. package/dist/fuzzy.js.map +1 -0
  94. package/dist/index.d.ts +34 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +46 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/keybindings.d.ts +366 -0
  99. package/dist/keybindings.d.ts.map +1 -0
  100. package/dist/keybindings.js +331 -0
  101. package/dist/keybindings.js.map +1 -0
  102. package/dist/keys.d.ts +184 -0
  103. package/dist/keys.d.ts.map +1 -0
  104. package/dist/keys.js +1174 -0
  105. package/dist/keys.js.map +1 -0
  106. package/dist/kill-ring.d.ts +28 -0
  107. package/dist/kill-ring.d.ts.map +1 -0
  108. package/dist/kill-ring.js +44 -0
  109. package/dist/kill-ring.js.map +1 -0
  110. package/dist/latex.d.ts +10 -0
  111. package/dist/latex.d.ts.map +1 -0
  112. package/dist/latex.js +1285 -0
  113. package/dist/latex.js.map +1 -0
  114. package/dist/layout-node.d.ts +59 -0
  115. package/dist/layout-node.d.ts.map +1 -0
  116. package/dist/layout-node.js +12 -0
  117. package/dist/layout-node.js.map +1 -0
  118. package/dist/layout.d.ts +42 -0
  119. package/dist/layout.d.ts.map +1 -0
  120. package/dist/layout.js +404 -0
  121. package/dist/layout.js.map +1 -0
  122. package/dist/native-modifiers.d.ts +4 -0
  123. package/dist/native-modifiers.d.ts.map +1 -0
  124. package/dist/native-modifiers.js +13 -0
  125. package/dist/native-modifiers.js.map +1 -0
  126. package/dist/native-module-path.d.ts +7 -0
  127. package/dist/native-module-path.d.ts.map +1 -0
  128. package/dist/native-module-path.js +19 -0
  129. package/dist/native-module-path.js.map +1 -0
  130. package/dist/native-platform.d.ts +18 -0
  131. package/dist/native-platform.d.ts.map +1 -0
  132. package/dist/native-platform.js +42 -0
  133. package/dist/native-platform.js.map +1 -0
  134. package/dist/pty-host.d.ts +224 -0
  135. package/dist/pty-host.d.ts.map +1 -0
  136. package/dist/pty-host.js +347 -0
  137. package/dist/pty-host.js.map +1 -0
  138. package/dist/stdin-buffer.d.ts +56 -0
  139. package/dist/stdin-buffer.d.ts.map +1 -0
  140. package/dist/stdin-buffer.js +366 -0
  141. package/dist/stdin-buffer.js.map +1 -0
  142. package/dist/terminal-colors.d.ts +10 -0
  143. package/dist/terminal-colors.d.ts.map +1 -0
  144. package/dist/terminal-colors.js +59 -0
  145. package/dist/terminal-colors.js.map +1 -0
  146. package/dist/terminal-image.d.ts +118 -0
  147. package/dist/terminal-image.d.ts.map +1 -0
  148. package/dist/terminal-image.js +550 -0
  149. package/dist/terminal-image.js.map +1 -0
  150. package/dist/terminal.d.ts +123 -0
  151. package/dist/terminal.d.ts.map +1 -0
  152. package/dist/terminal.js +442 -0
  153. package/dist/terminal.js.map +1 -0
  154. package/dist/tui-alt-screen.d.ts +165 -0
  155. package/dist/tui-alt-screen.d.ts.map +1 -0
  156. package/dist/tui-alt-screen.js +1515 -0
  157. package/dist/tui-alt-screen.js.map +1 -0
  158. package/dist/tui-main-screen.d.ts +39 -0
  159. package/dist/tui-main-screen.d.ts.map +1 -0
  160. package/dist/tui-main-screen.js +594 -0
  161. package/dist/tui-main-screen.js.map +1 -0
  162. package/dist/tui.d.ts +431 -0
  163. package/dist/tui.d.ts.map +1 -0
  164. package/dist/tui.js +1142 -0
  165. package/dist/tui.js.map +1 -0
  166. package/dist/undo-stack.d.ts +17 -0
  167. package/dist/undo-stack.d.ts.map +1 -0
  168. package/dist/undo-stack.js +25 -0
  169. package/dist/undo-stack.js.map +1 -0
  170. package/dist/utils.d.ts +98 -0
  171. package/dist/utils.d.ts.map +1 -0
  172. package/dist/utils.js +1200 -0
  173. package/dist/utils.js.map +1 -0
  174. package/dist/word-navigation.d.ts +25 -0
  175. package/dist/word-navigation.d.ts.map +1 -0
  176. package/dist/word-navigation.js +96 -0
  177. package/dist/word-navigation.js.map +1 -0
  178. package/native/clipboard.h +170 -0
  179. package/native/darwin/README.md +22 -0
  180. package/native/darwin/build.sh +69 -0
  181. package/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
  182. package/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
  183. package/native/darwin/src/darwin-platform.m +93 -0
  184. package/native/linux/README.md +23 -0
  185. package/native/linux/build.sh +65 -0
  186. package/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
  187. package/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
  188. package/native/linux/src/clipboard-worker.h +70 -0
  189. package/native/linux/src/linux-platform-x11.c +274 -0
  190. package/native/napi.h +89 -0
  191. package/native/win32/README.md +31 -0
  192. package/native/win32/build.mjs +232 -0
  193. package/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
  194. package/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
  195. package/native/win32/src/win32-platform.c +241 -0
  196. package/package.json +62 -0
package/dist/latex.js ADDED
@@ -0,0 +1,1285 @@
1
+ import { visibleWidth } from "./utils.js";
2
+ const SYMBOLS = {
3
+ alpha: "α",
4
+ beta: "β",
5
+ gamma: "γ",
6
+ delta: "δ",
7
+ epsilon: "ϵ",
8
+ varepsilon: "ε",
9
+ zeta: "ζ",
10
+ eta: "η",
11
+ theta: "θ",
12
+ vartheta: "ϑ",
13
+ iota: "ι",
14
+ kappa: "κ",
15
+ varkappa: "ϰ",
16
+ lambda: "λ",
17
+ mu: "μ",
18
+ nu: "ν",
19
+ xi: "ξ",
20
+ pi: "π",
21
+ varpi: "ϖ",
22
+ rho: "ρ",
23
+ varrho: "ϱ",
24
+ sigma: "σ",
25
+ varsigma: "ς",
26
+ tau: "τ",
27
+ upsilon: "υ",
28
+ phi: "ϕ",
29
+ varphi: "φ",
30
+ chi: "χ",
31
+ psi: "ψ",
32
+ omega: "ω",
33
+ Gamma: "Γ",
34
+ Delta: "Δ",
35
+ Theta: "Θ",
36
+ Lambda: "Λ",
37
+ Xi: "Ξ",
38
+ Pi: "Π",
39
+ Sigma: "Σ",
40
+ Upsilon: "Υ",
41
+ Phi: "Φ",
42
+ Psi: "Ψ",
43
+ Omega: "Ω",
44
+ pm: "±",
45
+ mp: "∓",
46
+ times: "×",
47
+ div: "÷",
48
+ cdot: "·",
49
+ ast: "∗",
50
+ star: "⋆",
51
+ circ: "∘",
52
+ bullet: "•",
53
+ oplus: "⊕",
54
+ ominus: "⊖",
55
+ otimes: "⊗",
56
+ oslash: "⊘",
57
+ odot: "⊙",
58
+ bigcirc: "○",
59
+ dagger: "†",
60
+ ddagger: "‡",
61
+ amalg: "⨿",
62
+ uplus: "⊎",
63
+ sqcap: "⊓",
64
+ sqcup: "⊔",
65
+ bowtie: "⋈",
66
+ Join: "⋈",
67
+ ltimes: "⋉",
68
+ rtimes: "⋊",
69
+ leftouterjoin: "⟕",
70
+ rightouterjoin: "⟖",
71
+ fullouterjoin: "⟗",
72
+ triangleleft: "◁",
73
+ triangleright: "▷",
74
+ wr: "≀",
75
+ cap: "∩",
76
+ cup: "∪",
77
+ bigcap: "⋂",
78
+ bigcup: "⋃",
79
+ bigwedge: "⋀",
80
+ bigvee: "⋁",
81
+ bigsqcup: "⨆",
82
+ biguplus: "⨄",
83
+ bigoplus: "⨁",
84
+ bigotimes: "⨂",
85
+ bigodot: "⨀",
86
+ setminus: "∖",
87
+ in: "∈",
88
+ notin: "∉",
89
+ ni: "∋",
90
+ subset: "⊂",
91
+ supset: "⊃",
92
+ subseteq: "⊆",
93
+ supseteq: "⊇",
94
+ sqsubset: "⊏",
95
+ sqsupset: "⊐",
96
+ sqsubseteq: "⊑",
97
+ sqsupseteq: "⊒",
98
+ prec: "≺",
99
+ preceq: "≼",
100
+ succ: "≻",
101
+ succeq: "≽",
102
+ ll: "≪",
103
+ gg: "≫",
104
+ le: "≤",
105
+ leq: "≤",
106
+ leqslant: "≤",
107
+ ge: "≥",
108
+ geq: "≥",
109
+ geqslant: "≥",
110
+ ne: "≠",
111
+ neq: "≠",
112
+ equiv: "≡",
113
+ approx: "≈",
114
+ sim: "∼",
115
+ simeq: "≃",
116
+ cong: "≅",
117
+ asymp: "≍",
118
+ doteq: "≐",
119
+ propto: "∝",
120
+ parallel: "∥",
121
+ perp: "⊥",
122
+ mid: "∣",
123
+ vdash: "⊢",
124
+ dashv: "⊣",
125
+ models: "⊨",
126
+ Vdash: "⊩",
127
+ Vvdash: "⊪",
128
+ nvdash: "⊬",
129
+ nvDash: "⊭",
130
+ forall: "∀",
131
+ exists: "∃",
132
+ nexists: "∄",
133
+ neg: "¬",
134
+ land: "∧",
135
+ wedge: "∧",
136
+ lor: "∨",
137
+ vee: "∨",
138
+ to: "→",
139
+ rightarrow: "→",
140
+ longrightarrow: "→",
141
+ leftarrow: "←",
142
+ longleftarrow: "←",
143
+ gets: "←",
144
+ leftrightarrow: "↔",
145
+ longleftrightarrow: "↔",
146
+ hookleftarrow: "↩",
147
+ hookrightarrow: "↪",
148
+ twoheadleftarrow: "↞",
149
+ twoheadrightarrow: "↠",
150
+ leftharpoonup: "↼",
151
+ leftharpoondown: "↽",
152
+ rightharpoonup: "⇀",
153
+ rightharpoondown: "⇁",
154
+ rightleftharpoons: "⇌",
155
+ leftrightharpoons: "⇋",
156
+ nearrow: "↗",
157
+ searrow: "↘",
158
+ swarrow: "↙",
159
+ nwarrow: "↖",
160
+ rightsquigarrow: "⇝",
161
+ leadsto: "⇝",
162
+ Rightarrow: "⇒",
163
+ Longrightarrow: "⇒",
164
+ Leftarrow: "⇐",
165
+ Longleftarrow: "⇐",
166
+ Leftrightarrow: "⇔",
167
+ Longleftrightarrow: "⇔",
168
+ implies: "⇒",
169
+ iff: "⇔",
170
+ mapsto: "↦",
171
+ longmapsto: "↦",
172
+ uparrow: "↑",
173
+ downarrow: "↓",
174
+ partial: "∂",
175
+ nabla: "∇",
176
+ int: "∫",
177
+ iint: "∬",
178
+ iiint: "∭",
179
+ oint: "∮",
180
+ sum: "∑",
181
+ prod: "∏",
182
+ coprod: "∐",
183
+ infty: "∞",
184
+ emptyset: "∅",
185
+ varnothing: "∅",
186
+ angle: "∠",
187
+ therefore: "∴",
188
+ because: "∵",
189
+ aleph: "ℵ",
190
+ beth: "ℶ",
191
+ gimel: "ℷ",
192
+ daleth: "ℸ",
193
+ top: "⊤",
194
+ bot: "⊥",
195
+ triangle: "△",
196
+ square: "□",
197
+ lozenge: "◊",
198
+ checkmark: "✓",
199
+ complement: "∁",
200
+ wp: "℘",
201
+ prime: "′",
202
+ ldots: "…",
203
+ dots: "…",
204
+ cdots: "⋯",
205
+ vdots: "⋮",
206
+ ddots: "⋱",
207
+ ell: "ℓ",
208
+ hbar: "ℏ",
209
+ Im: "ℑ",
210
+ Re: "ℜ",
211
+ langle: "⟨",
212
+ rangle: "⟩",
213
+ vert: "|",
214
+ lvert: "|",
215
+ rvert: "|",
216
+ Vert: "‖",
217
+ lVert: "‖",
218
+ rVert: "‖",
219
+ lbrace: "{",
220
+ rbrace: "}",
221
+ backslash: "\\",
222
+ lfloor: "⌊",
223
+ rfloor: "⌋",
224
+ lceil: "⌈",
225
+ rceil: "⌉",
226
+ colon: ":",
227
+ };
228
+ const NAMED_OPERATORS = new Set([
229
+ "arccos",
230
+ "arcsin",
231
+ "arctan",
232
+ "arg",
233
+ "cos",
234
+ "cosh",
235
+ "cot",
236
+ "coth",
237
+ "csc",
238
+ "deg",
239
+ "det",
240
+ "dim",
241
+ "exp",
242
+ "gcd",
243
+ "hom",
244
+ "inf",
245
+ "ker",
246
+ "lg",
247
+ "lim",
248
+ "liminf",
249
+ "limsup",
250
+ "ln",
251
+ "log",
252
+ "max",
253
+ "min",
254
+ "Pr",
255
+ "sec",
256
+ "sin",
257
+ "sinh",
258
+ "sup",
259
+ "tan",
260
+ "tanh",
261
+ ]);
262
+ const LIMIT_OPERATORS = new Set([
263
+ "argmax",
264
+ "argmin",
265
+ "inf",
266
+ "injlim",
267
+ "lim",
268
+ "liminf",
269
+ "limsup",
270
+ "max",
271
+ "min",
272
+ "projlim",
273
+ "sup",
274
+ ]);
275
+ const DISPLAY_LIMIT_SYMBOLS = new Set([
276
+ "bigcap",
277
+ "bigcup",
278
+ "bigodot",
279
+ "bigoplus",
280
+ "bigotimes",
281
+ "bigsqcup",
282
+ "biguplus",
283
+ "bigvee",
284
+ "bigwedge",
285
+ "coprod",
286
+ "int",
287
+ "iint",
288
+ "iiint",
289
+ "oint",
290
+ "prod",
291
+ "sum",
292
+ ]);
293
+ const RELATION_COMMANDS = new Set([
294
+ "Leftarrow",
295
+ "Leftrightarrow",
296
+ "Longleftarrow",
297
+ "Longleftrightarrow",
298
+ "Longrightarrow",
299
+ "Rightarrow",
300
+ "Join",
301
+ "Vdash",
302
+ "Vvdash",
303
+ "approx",
304
+ "asymp",
305
+ "bowtie",
306
+ "cong",
307
+ "dashv",
308
+ "fullouterjoin",
309
+ "doteq",
310
+ "downarrow",
311
+ "equiv",
312
+ "ge",
313
+ "geq",
314
+ "geqslant",
315
+ "gets",
316
+ "gg",
317
+ "hookleftarrow",
318
+ "hookrightarrow",
319
+ "iff",
320
+ "implies",
321
+ "in",
322
+ "leadsto",
323
+ "le",
324
+ "leftarrow",
325
+ "leftharpoondown",
326
+ "leftharpoonup",
327
+ "leftrightarrow",
328
+ "leftrightharpoons",
329
+ "leftouterjoin",
330
+ "leq",
331
+ "leqslant",
332
+ "ll",
333
+ "longleftarrow",
334
+ "longleftrightarrow",
335
+ "longmapsto",
336
+ "longrightarrow",
337
+ "ltimes",
338
+ "mapsto",
339
+ "mid",
340
+ "models",
341
+ "ne",
342
+ "nearrow",
343
+ "neq",
344
+ "ni",
345
+ "notin",
346
+ "nvdash",
347
+ "nvDash",
348
+ "nwarrow",
349
+ "parallel",
350
+ "perp",
351
+ "prec",
352
+ "preceq",
353
+ "propto",
354
+ "rightharpoondown",
355
+ "rightharpoonup",
356
+ "rightleftharpoons",
357
+ "rightouterjoin",
358
+ "rightarrow",
359
+ "rightsquigarrow",
360
+ "rtimes",
361
+ "searrow",
362
+ "sim",
363
+ "simeq",
364
+ "sqsubset",
365
+ "sqsubseteq",
366
+ "sqsupset",
367
+ "sqsupseteq",
368
+ "subset",
369
+ "subseteq",
370
+ "succ",
371
+ "succeq",
372
+ "supset",
373
+ "supseteq",
374
+ "swarrow",
375
+ "to",
376
+ "triangleleft",
377
+ "triangleright",
378
+ "twoheadleftarrow",
379
+ "twoheadrightarrow",
380
+ "uparrow",
381
+ "vdash",
382
+ ]);
383
+ const NEGATED_SYMBOLS = {
384
+ "<": "≮",
385
+ ">": "≯",
386
+ "=": "≠",
387
+ "∈": "∉",
388
+ "∋": "∌",
389
+ "∣": "∤",
390
+ "∥": "∦",
391
+ "∼": "≁",
392
+ "≃": "≄",
393
+ "≅": "≇",
394
+ "≈": "≉",
395
+ "≡": "≢",
396
+ "≤": "≰",
397
+ "≥": "≱",
398
+ "≺": "⊀",
399
+ "≻": "⊁",
400
+ "⊂": "⊄",
401
+ "⊃": "⊅",
402
+ "⊆": "⊈",
403
+ "⊇": "⊉",
404
+ "⊢": "⊬",
405
+ "⊨": "⊭",
406
+ "↔": "↮",
407
+ "←": "↚",
408
+ "→": "↛",
409
+ "⇒": "⇏",
410
+ "⇐": "⇍",
411
+ "⇔": "⇎",
412
+ "≼": "⋠",
413
+ "≽": "⋡",
414
+ };
415
+ const BLACKBOARD = {
416
+ C: "ℂ",
417
+ H: "ℍ",
418
+ N: "ℕ",
419
+ P: "ℙ",
420
+ Q: "ℚ",
421
+ R: "ℝ",
422
+ Z: "ℤ",
423
+ };
424
+ const SUPERSCRIPTS = {
425
+ "0": "⁰",
426
+ "1": "¹",
427
+ "2": "²",
428
+ "3": "³",
429
+ "4": "⁴",
430
+ "5": "⁵",
431
+ "6": "⁶",
432
+ "7": "⁷",
433
+ "8": "⁸",
434
+ "9": "⁹",
435
+ "+": "⁺",
436
+ "-": "⁻",
437
+ "=": "⁼",
438
+ "(": "⁽",
439
+ ")": "⁾",
440
+ a: "ᵃ",
441
+ b: "ᵇ",
442
+ c: "ᶜ",
443
+ d: "ᵈ",
444
+ e: "ᵉ",
445
+ f: "ᶠ",
446
+ g: "ᵍ",
447
+ h: "ʰ",
448
+ i: "ⁱ",
449
+ j: "ʲ",
450
+ k: "ᵏ",
451
+ l: "ˡ",
452
+ m: "ᵐ",
453
+ n: "ⁿ",
454
+ o: "ᵒ",
455
+ p: "ᵖ",
456
+ r: "ʳ",
457
+ s: "ˢ",
458
+ t: "ᵗ",
459
+ u: "ᵘ",
460
+ v: "ᵛ",
461
+ w: "ʷ",
462
+ x: "ˣ",
463
+ y: "ʸ",
464
+ z: "ᶻ",
465
+ };
466
+ const SUBSCRIPTS = {
467
+ "0": "₀",
468
+ "1": "₁",
469
+ "2": "₂",
470
+ "3": "₃",
471
+ "4": "₄",
472
+ "5": "₅",
473
+ "6": "₆",
474
+ "7": "₇",
475
+ "8": "₈",
476
+ "9": "₉",
477
+ "+": "₊",
478
+ "-": "₋",
479
+ "=": "₌",
480
+ "(": "₍",
481
+ ")": "₎",
482
+ a: "ₐ",
483
+ e: "ₑ",
484
+ h: "ₕ",
485
+ i: "ᵢ",
486
+ j: "ⱼ",
487
+ k: "ₖ",
488
+ l: "ₗ",
489
+ m: "ₘ",
490
+ n: "ₙ",
491
+ o: "ₒ",
492
+ p: "ₚ",
493
+ r: "ᵣ",
494
+ s: "ₛ",
495
+ t: "ₜ",
496
+ u: "ᵤ",
497
+ v: "ᵥ",
498
+ x: "ₓ",
499
+ };
500
+ const SPACING_COMMANDS = new Set([
501
+ ",",
502
+ ":",
503
+ ";",
504
+ " ",
505
+ ">",
506
+ "enspace",
507
+ "enskip",
508
+ "medspace",
509
+ "quad",
510
+ "qquad",
511
+ "thickspace",
512
+ "thinspace",
513
+ ]);
514
+ const NEGATIVE_SPACING_COMMANDS = new Set(["!", "negmedspace", "negthickspace", "negthinspace"]);
515
+ const NEGATIVE_SPACE = "\u0000";
516
+ const IGNORED_COMMANDS = new Set([
517
+ "displaystyle",
518
+ "limits",
519
+ "nolimits",
520
+ "scriptstyle",
521
+ "scriptscriptstyle",
522
+ "textstyle",
523
+ ]);
524
+ const SIZE_COMMANDS = new Set([
525
+ "big",
526
+ "Big",
527
+ "bigg",
528
+ "Bigg",
529
+ "bigl",
530
+ "Bigl",
531
+ "biggl",
532
+ "Biggl",
533
+ "bigr",
534
+ "Bigr",
535
+ "biggr",
536
+ "Biggr",
537
+ ]);
538
+ const PLAIN_WRAPPERS = new Set([
539
+ "emph",
540
+ "mathcal",
541
+ "mathbf",
542
+ "mathfrak",
543
+ "mathit",
544
+ "mathrm",
545
+ "mathnormal",
546
+ "mathscr",
547
+ "mathsf",
548
+ "mathtt",
549
+ "mathup",
550
+ "mbox",
551
+ "overbrace",
552
+ "pmb",
553
+ "smash",
554
+ "substack",
555
+ "text",
556
+ "textbf",
557
+ "textit",
558
+ "textmd",
559
+ "textnormal",
560
+ "textrm",
561
+ "textsc",
562
+ "textsf",
563
+ "textsl",
564
+ "texttt",
565
+ "textup",
566
+ "underbrace",
567
+ "bm",
568
+ "boldsymbol",
569
+ ]);
570
+ const ACCENTS = {
571
+ acute: "\u0301",
572
+ bar: "\u0305",
573
+ breve: "\u0306",
574
+ check: "\u030c",
575
+ ddot: "\u0308",
576
+ dot: "\u0307",
577
+ grave: "\u0300",
578
+ hat: "\u0302",
579
+ mathring: "\u030a",
580
+ overleftarrow: "\u20d6",
581
+ overleftrightarrow: "\u20e1",
582
+ overline: "\u0305",
583
+ overrightarrow: "\u20d7",
584
+ tilde: "\u0303",
585
+ underline: "\u0332",
586
+ vec: "\u20d7",
587
+ widehat: "\u0302",
588
+ widetilde: "\u0303",
589
+ };
590
+ function replaceCharacters(value, replacements) {
591
+ let result = "";
592
+ for (const character of value) {
593
+ const replacement = replacements[character];
594
+ if (replacement === undefined) {
595
+ return undefined;
596
+ }
597
+ result += replacement;
598
+ }
599
+ return result;
600
+ }
601
+ function formatScript(value, kind) {
602
+ value = value.trim();
603
+ const replacements = kind === "sub" ? SUBSCRIPTS : SUPERSCRIPTS;
604
+ const unicode = replaceCharacters(value.replace(/\s*([=+-])\s*/g, "$1"), replacements);
605
+ if (unicode !== undefined) {
606
+ return unicode;
607
+ }
608
+ const prefix = kind === "sub" ? "_" : "^";
609
+ if (Array.from(value).length === 1 || (kind === "sub" && /^[A-Za-z]+$/.test(value))) {
610
+ return `${prefix}${value}`;
611
+ }
612
+ return `${prefix}(${value})`;
613
+ }
614
+ function formatFraction(numerator, denominator) {
615
+ numerator = numerator.trim();
616
+ denominator = denominator.trim();
617
+ const simpleNumerator = /^[\p{L}\p{N}.]+$/u.test(numerator);
618
+ const simpleDenominator = /^[\p{N}.]+$/u.test(denominator) || Array.from(denominator).length === 1;
619
+ return `${simpleNumerator ? numerator : `(${numerator})`}/${simpleDenominator ? denominator : `(${denominator})`}`;
620
+ }
621
+ function formatRoot(value, symbol = "√") {
622
+ value = value.trim();
623
+ return /^[\p{L}\p{N}.]+$/u.test(value) ? `${symbol}${value}` : `${symbol}(${value})`;
624
+ }
625
+ const NAMED_OPERATOR_START = "\u{f0004}";
626
+ const NAMED_OPERATOR_END = "\u{f0005}";
627
+ const NAMED_OPERATOR_LEFT_SPACING_PATTERN = /(?<=[\p{L}\p{N})\]}\u{f0001}])\u{f0004}/gu;
628
+ const NAMED_OPERATOR_RIGHT_SPACING_PATTERN = /\u{f0005}(?=[\p{L}\p{N}√\u{f0000}])/gu;
629
+ function normalizeOutput(value) {
630
+ return value
631
+ .replace(NAMED_OPERATOR_LEFT_SPACING_PATTERN, " ")
632
+ .replaceAll(NAMED_OPERATOR_START, "")
633
+ .replace(NAMED_OPERATOR_RIGHT_SPACING_PATTERN, " ")
634
+ .replaceAll(NAMED_OPERATOR_END, "")
635
+ .split("\n")
636
+ .map((line) => line.replace(/[ \t]+/g, " ").trim())
637
+ .filter((line, index, lines) => line.length > 0 || (index > 0 && index < lines.length - 1))
638
+ .join("\n")
639
+ .trim();
640
+ }
641
+ const LAYOUT_MARKER_START = "\u{f0000}";
642
+ const LAYOUT_MARKER_END = "\u{f0001}";
643
+ const LAYOUT_MARKER_PATTERN = /\u{f0000}(\d+)\u{f0001}/gu;
644
+ const TRAILING_LAYOUT_MARKER_PATTERN = /\u{f0000}(\d+)\u{f0001}$/u;
645
+ const PROTECTED_SPACE = "\u{f0002}";
646
+ function padLayoutLine(line, width, centered = false) {
647
+ const padding = Math.max(0, width - visibleWidth(line));
648
+ const left = centered ? Math.floor(padding / 2) : 0;
649
+ return `${" ".repeat(left)}${line}${" ".repeat(padding - left)}`;
650
+ }
651
+ function joinLayouts(layouts) {
652
+ if (layouts.length === 0) {
653
+ return { lines: [""], width: 0, baseline: 0 };
654
+ }
655
+ const baseline = Math.max(...layouts.map((layout) => layout.baseline));
656
+ const below = Math.max(...layouts.map((layout) => layout.lines.length - layout.baseline - 1));
657
+ const lines = [];
658
+ for (let row = 0; row <= baseline + below; row++) {
659
+ let line = "";
660
+ for (const layout of layouts) {
661
+ const sourceRow = row - baseline + layout.baseline;
662
+ line +=
663
+ sourceRow >= 0 && sourceRow < layout.lines.length
664
+ ? padLayoutLine(layout.lines[sourceRow] ?? "", layout.width)
665
+ : " ".repeat(layout.width);
666
+ }
667
+ lines.push(line.trimEnd());
668
+ }
669
+ return {
670
+ lines,
671
+ width: layouts.reduce((width, layout) => width + layout.width, 0),
672
+ baseline,
673
+ };
674
+ }
675
+ function renderLayout(source, nodes) {
676
+ const renderedLines = [];
677
+ let firstBaseline = 0;
678
+ for (const sourceLine of source.split("\n")) {
679
+ const layouts = [];
680
+ let position = 0;
681
+ let previousNode;
682
+ for (const match of sourceLine.matchAll(LAYOUT_MARKER_PATTERN)) {
683
+ const index = match.index;
684
+ const node = nodes[Number(match[1])];
685
+ if (!node) {
686
+ continue;
687
+ }
688
+ if (index > position) {
689
+ const sliced = sourceLine.slice(position, index);
690
+ const trimmed = (previousNode ? sliced.trimStart() : sliced).trimEnd();
691
+ const preserveLeadingSpace = previousNode?.type === "matrix" && /^\s/.test(sliced);
692
+ const preserveTrailingSpace = node.type === "matrix" && /\s$/.test(sliced);
693
+ const text = trimmed
694
+ ? `${preserveLeadingSpace ? " " : ""}${trimmed}${preserveTrailingSpace ? " " : ""}`
695
+ : preserveLeadingSpace || preserveTrailingSpace
696
+ ? " "
697
+ : "";
698
+ layouts.push({ lines: [text], width: visibleWidth(text), baseline: 0 });
699
+ }
700
+ if (node.type === "fraction") {
701
+ const numerator = renderLayout(node.numerator, nodes);
702
+ const denominator = renderLayout(node.denominator, nodes);
703
+ const contentWidth = Math.max(numerator.width, denominator.width, 1);
704
+ const width = contentWidth + 2;
705
+ layouts.push({
706
+ lines: [
707
+ ...numerator.lines.map((line) => padLayoutLine(line, width, true)),
708
+ ` ${"─".repeat(contentWidth)} `,
709
+ ...denominator.lines.map((line) => padLayoutLine(line, width, true)),
710
+ ],
711
+ width,
712
+ baseline: numerator.lines.length,
713
+ });
714
+ }
715
+ else if (node.type === "operator") {
716
+ const contentWidth = Math.max(visibleWidth(node.operator), node.lower === undefined ? 0 : visibleWidth(node.lower), node.upper === undefined ? 0 : visibleWidth(node.upper));
717
+ const lines = [];
718
+ if (node.upper !== undefined) {
719
+ lines.push(`${padLayoutLine(node.upper, contentWidth, true)} `);
720
+ }
721
+ lines.push(`${padLayoutLine(node.operator, contentWidth, true)} `);
722
+ if (node.lower !== undefined) {
723
+ lines.push(`${padLayoutLine(node.lower, contentWidth, true)} `);
724
+ }
725
+ layouts.push({
726
+ lines,
727
+ width: contentWidth + 1,
728
+ baseline: node.upper === undefined ? 0 : 1,
729
+ });
730
+ }
731
+ else {
732
+ const width = Math.max(0, ...node.lines.map((line) => visibleWidth(line)));
733
+ layouts.push({
734
+ lines: node.lines.map((line) => padLayoutLine(line, width)),
735
+ width,
736
+ baseline: node.baseline,
737
+ });
738
+ }
739
+ position = index + match[0].length;
740
+ previousNode = node;
741
+ }
742
+ if (position < sourceLine.length) {
743
+ const sliced = sourceLine.slice(position);
744
+ const trimmed = previousNode ? sliced.trimStart() : sliced;
745
+ const text = previousNode?.type === "matrix" && /^\s/.test(sliced) ? ` ${trimmed}` : trimmed;
746
+ layouts.push({ lines: [text], width: visibleWidth(text), baseline: 0 });
747
+ }
748
+ const lineLayout = joinLayouts(layouts);
749
+ if (renderedLines.length === 0) {
750
+ firstBaseline = lineLayout.baseline;
751
+ }
752
+ renderedLines.push(...lineLayout.lines);
753
+ }
754
+ return {
755
+ lines: renderedLines,
756
+ width: Math.max(0, ...renderedLines.map((line) => visibleWidth(line))),
757
+ baseline: firstBaseline,
758
+ };
759
+ }
760
+ class LatexParser {
761
+ source;
762
+ layoutNodes;
763
+ display;
764
+ position = 0;
765
+ supported = true;
766
+ stackFractions = true;
767
+ constructor(source, layoutNodes, display) {
768
+ this.source = source;
769
+ this.layoutNodes = layoutNodes;
770
+ this.display = display;
771
+ }
772
+ render() {
773
+ const rendered = this.parseSequence();
774
+ if (!this.supported || this.position !== this.source.length) {
775
+ return undefined;
776
+ }
777
+ return normalizeOutput(rendered);
778
+ }
779
+ parseSequence(endCharacter) {
780
+ let result = "";
781
+ while (this.position < this.source.length) {
782
+ const character = this.source[this.position];
783
+ if (endCharacter && character === endCharacter) {
784
+ this.position++;
785
+ return result;
786
+ }
787
+ if (character === "}") {
788
+ this.supported = false;
789
+ return result;
790
+ }
791
+ if (character === "{") {
792
+ this.position++;
793
+ result += this.parseSequence("}");
794
+ continue;
795
+ }
796
+ if (character === "\\") {
797
+ const command = this.parseCommand();
798
+ if (command === NEGATIVE_SPACE) {
799
+ result = result.trimEnd();
800
+ if (result.endsWith(NAMED_OPERATOR_END)) {
801
+ result = result.slice(0, -NAMED_OPERATOR_END.length);
802
+ }
803
+ }
804
+ else {
805
+ result += command;
806
+ }
807
+ continue;
808
+ }
809
+ if (character === "^" || character === "_") {
810
+ this.position++;
811
+ result = result.trimEnd();
812
+ const script = formatScript(this.parseRequiredArgument(false), character === "_" ? "sub" : "sup");
813
+ if (result.endsWith(NAMED_OPERATOR_END)) {
814
+ result = `${result.slice(0, -NAMED_OPERATOR_END.length)}${script}${NAMED_OPERATOR_END}`;
815
+ }
816
+ else {
817
+ result += script;
818
+ }
819
+ continue;
820
+ }
821
+ if (/\s/.test(character)) {
822
+ result += this.parseWhitespace();
823
+ continue;
824
+ }
825
+ if (character === "=" || character === "<" || character === ">") {
826
+ result = `${result.trimEnd()} ${character} `;
827
+ this.position++;
828
+ continue;
829
+ }
830
+ if (character === "&") {
831
+ this.position++;
832
+ continue;
833
+ }
834
+ if (character === "~") {
835
+ this.position++;
836
+ result += " ";
837
+ continue;
838
+ }
839
+ if (character === ".") {
840
+ const marker = TRAILING_LAYOUT_MARKER_PATTERN.exec(result);
841
+ const node = marker ? this.layoutNodes[Number(marker[1])] : undefined;
842
+ if (node?.type === "matrix") {
843
+ const lastLine = node.lines.length - 1;
844
+ node.lines[lastLine] = `${node.lines[lastLine] ?? ""}${character}`;
845
+ this.position++;
846
+ continue;
847
+ }
848
+ }
849
+ result += character;
850
+ this.position++;
851
+ }
852
+ if (endCharacter) {
853
+ this.supported = false;
854
+ }
855
+ return result;
856
+ }
857
+ parseWhitespace() {
858
+ while (this.position < this.source.length && /\s/.test(this.source[this.position] ?? "")) {
859
+ this.position++;
860
+ }
861
+ return " ";
862
+ }
863
+ parseCommand() {
864
+ this.position++;
865
+ if (this.position >= this.source.length) {
866
+ this.supported = false;
867
+ return "";
868
+ }
869
+ let command = "";
870
+ const first = this.source[this.position] ?? "";
871
+ if (first === "\n" || first === "\r") {
872
+ this.position++;
873
+ if (first === "\r" && this.source[this.position] === "\n") {
874
+ this.position++;
875
+ }
876
+ return " ";
877
+ }
878
+ if (/[A-Za-z]/.test(first)) {
879
+ const start = this.position;
880
+ while (this.position < this.source.length && /[A-Za-z]/.test(this.source[this.position] ?? "")) {
881
+ this.position++;
882
+ }
883
+ command = this.source.slice(start, this.position);
884
+ }
885
+ else {
886
+ command = first;
887
+ this.position++;
888
+ }
889
+ if (command === "\\") {
890
+ return "\n";
891
+ }
892
+ if (SPACING_COMMANDS.has(command)) {
893
+ return " ";
894
+ }
895
+ if (NEGATIVE_SPACING_COMMANDS.has(command)) {
896
+ return NEGATIVE_SPACE;
897
+ }
898
+ if (IGNORED_COMMANDS.has(command)) {
899
+ return "";
900
+ }
901
+ if (command === "{" ||
902
+ command === "}" ||
903
+ command === "$" ||
904
+ command === "%" ||
905
+ command === "#" ||
906
+ command === "_" ||
907
+ command === "&") {
908
+ return command;
909
+ }
910
+ if (command === "|") {
911
+ return "‖";
912
+ }
913
+ if (command === "not") {
914
+ const value = this.parseRequiredArgument(false).trim();
915
+ const negated = NEGATED_SYMBOLS[value];
916
+ if (negated !== undefined) {
917
+ return ` ${negated} `;
918
+ }
919
+ const characters = Array.from(value);
920
+ if (characters.length === 0) {
921
+ this.supported = false;
922
+ return "";
923
+ }
924
+ return ` ${characters[0]}\u0338${characters.slice(1).join("")} `;
925
+ }
926
+ if (LIMIT_OPERATORS.has(command)) {
927
+ return this.parseOperator(command, "bracket", true, true);
928
+ }
929
+ const symbol = SYMBOLS[command];
930
+ if (symbol !== undefined) {
931
+ if (DISPLAY_LIMIT_SYMBOLS.has(command)) {
932
+ return this.parseOperator(symbol, "script", true);
933
+ }
934
+ return command === "cdot" || command === "times" || RELATION_COMMANDS.has(command) ? ` ${symbol} ` : symbol;
935
+ }
936
+ if (NAMED_OPERATORS.has(command)) {
937
+ return `${NAMED_OPERATOR_START}${command}${NAMED_OPERATOR_END}`;
938
+ }
939
+ if (SIZE_COMMANDS.has(command)) {
940
+ return "";
941
+ }
942
+ if (command === "left" || command === "middle" || command === "right") {
943
+ if (this.source[this.position] === ".") {
944
+ this.position++;
945
+ }
946
+ return "";
947
+ }
948
+ if (command === "frac" || command === "dfrac" || command === "tfrac") {
949
+ const shouldStack = this.display && this.stackFractions && command !== "tfrac";
950
+ const numerator = this.parseRequiredArgument(!shouldStack);
951
+ const denominator = this.parseRequiredArgument(!shouldStack);
952
+ if (shouldStack) {
953
+ const index = this.layoutNodes.push({
954
+ type: "fraction",
955
+ numerator: normalizeOutput(numerator),
956
+ denominator: normalizeOutput(denominator),
957
+ }) - 1;
958
+ return `${LAYOUT_MARKER_START}${index}${LAYOUT_MARKER_END}`;
959
+ }
960
+ return formatFraction(numerator, denominator);
961
+ }
962
+ if (command === "sqrt") {
963
+ const degree = this.parseOptionalArgument()?.trim();
964
+ const value = this.parseRequiredArgument();
965
+ if (degree === undefined || degree === "2") {
966
+ return formatRoot(value);
967
+ }
968
+ if (degree === "3") {
969
+ return formatRoot(value, "∛");
970
+ }
971
+ if (degree === "4") {
972
+ return formatRoot(value, "∜");
973
+ }
974
+ return `${formatScript(degree, "sup")}${formatRoot(value)}`;
975
+ }
976
+ if (command === "boxed" || command === "fbox") {
977
+ return `[${this.parseRequiredArgument().trim()}]`;
978
+ }
979
+ if (command === "binom" || command === "dbinom" || command === "tbinom") {
980
+ return `(${this.parseRequiredArgument()} choose ${this.parseRequiredArgument()})`;
981
+ }
982
+ const accent = ACCENTS[command];
983
+ if (accent !== undefined) {
984
+ const value = this.parseRequiredArgument();
985
+ return Array.from(value).length === 1 ? `${value}${accent}` : `${command}(${value})`;
986
+ }
987
+ if (command === "mathbb") {
988
+ const value = this.parseRequiredArgument();
989
+ return Array.from(value, (character) => BLACKBOARD[character] ?? character).join("");
990
+ }
991
+ if (command === "operatorname") {
992
+ const starred = this.source[this.position] === "*";
993
+ if (starred) {
994
+ this.position++;
995
+ }
996
+ const operator = normalizeOutput(this.parseRequiredArgument()).trim();
997
+ return this.parseOperator(operator, "bracket", starred, true);
998
+ }
999
+ if (command === "mod" || command === "bmod") {
1000
+ return " mod ";
1001
+ }
1002
+ if (command === "pmod" || command === "pod") {
1003
+ const value = this.parseRequiredArgument().trim();
1004
+ return command === "pmod" ? ` (mod ${value})` : ` (${value})`;
1005
+ }
1006
+ if (command === "overset" || command === "stackrel") {
1007
+ const upper = this.parseRequiredArgument();
1008
+ const value = this.parseRequiredArgument().trim();
1009
+ return `${value}${formatScript(upper, "sup")}`;
1010
+ }
1011
+ if (command === "underset") {
1012
+ const lower = this.parseRequiredArgument();
1013
+ const value = this.parseRequiredArgument().trim();
1014
+ return `${value}${formatScript(lower, "sub")}`;
1015
+ }
1016
+ if (PLAIN_WRAPPERS.has(command)) {
1017
+ const value = this.parseRequiredArgument();
1018
+ return command.startsWith("text") || command === "mbox" ? value : value.trim();
1019
+ }
1020
+ if (command === "begin") {
1021
+ return this.parseEnvironment();
1022
+ }
1023
+ if (command === "end") {
1024
+ this.supported = false;
1025
+ return "";
1026
+ }
1027
+ this.supported = false;
1028
+ return `\\${command}`;
1029
+ }
1030
+ parseOperator(operator, inlineLowerStyle, displayLimits, spaced = false) {
1031
+ let useDisplayLimits = displayLimits;
1032
+ let modifierPosition = this.position;
1033
+ while (modifierPosition < this.source.length && /[ \t]/.test(this.source[modifierPosition] ?? "")) {
1034
+ modifierPosition++;
1035
+ }
1036
+ const modifier = /^\\(limits|nolimits)(?![A-Za-z])/.exec(this.source.slice(modifierPosition));
1037
+ if (modifier) {
1038
+ useDisplayLimits = modifier[1] === "limits";
1039
+ this.position = modifierPosition + modifier[0].length;
1040
+ }
1041
+ let lower;
1042
+ let upper;
1043
+ while (true) {
1044
+ let scriptPosition = this.position;
1045
+ while (scriptPosition < this.source.length && /[ \t]/.test(this.source[scriptPosition] ?? "")) {
1046
+ scriptPosition++;
1047
+ }
1048
+ const kind = this.source[scriptPosition];
1049
+ if (kind !== "_" && kind !== "^") {
1050
+ break;
1051
+ }
1052
+ this.position = scriptPosition + 1;
1053
+ const value = normalizeOutput(this.parseRequiredArgument(false)).replaceAll(" ", "");
1054
+ if (kind === "_") {
1055
+ if (lower !== undefined) {
1056
+ this.supported = false;
1057
+ }
1058
+ lower = value;
1059
+ }
1060
+ else {
1061
+ if (upper !== undefined) {
1062
+ this.supported = false;
1063
+ }
1064
+ upper = value;
1065
+ }
1066
+ }
1067
+ if (this.display && useDisplayLimits && (lower !== undefined || upper !== undefined)) {
1068
+ const index = this.layoutNodes.push({ type: "operator", operator, lower, upper }) - 1;
1069
+ return `${LAYOUT_MARKER_START}${index}${LAYOUT_MARKER_END}`;
1070
+ }
1071
+ let rendered = operator;
1072
+ if (lower !== undefined) {
1073
+ rendered += inlineLowerStyle === "bracket" ? `[${lower}]` : formatScript(lower, "sub");
1074
+ }
1075
+ if (upper !== undefined) {
1076
+ rendered += formatScript(upper, "sup");
1077
+ }
1078
+ return spaced ? ` ${rendered} ` : rendered;
1079
+ }
1080
+ parseRequiredArgument(stackFractions = true) {
1081
+ const previousStackFractions = this.stackFractions;
1082
+ this.stackFractions = previousStackFractions && stackFractions;
1083
+ const value = this.parseRequiredArgumentValue();
1084
+ this.stackFractions = previousStackFractions;
1085
+ return value;
1086
+ }
1087
+ parseRequiredArgumentValue() {
1088
+ while (this.position < this.source.length && /\s/.test(this.source[this.position] ?? "")) {
1089
+ this.position++;
1090
+ }
1091
+ if (this.position >= this.source.length) {
1092
+ this.supported = false;
1093
+ return "";
1094
+ }
1095
+ if (this.source[this.position] === "{") {
1096
+ this.position++;
1097
+ return this.parseSequence("}");
1098
+ }
1099
+ if (this.source[this.position] === "\\") {
1100
+ return this.parseCommand();
1101
+ }
1102
+ const value = this.source[this.position] ?? "";
1103
+ this.position++;
1104
+ return value;
1105
+ }
1106
+ parseOptionalArgument() {
1107
+ while (this.position < this.source.length && /[ \t]/.test(this.source[this.position] ?? "")) {
1108
+ this.position++;
1109
+ }
1110
+ if (this.source[this.position] !== "[") {
1111
+ return undefined;
1112
+ }
1113
+ const end = this.source.indexOf("]", this.position + 1);
1114
+ if (end < 0) {
1115
+ this.supported = false;
1116
+ return undefined;
1117
+ }
1118
+ const value = this.source.slice(this.position + 1, end);
1119
+ this.position = end + 1;
1120
+ return this.renderNested(value);
1121
+ }
1122
+ readRawGroup() {
1123
+ while (this.position < this.source.length && /[ \t]/.test(this.source[this.position] ?? "")) {
1124
+ this.position++;
1125
+ }
1126
+ if (this.source[this.position] !== "{") {
1127
+ this.supported = false;
1128
+ return undefined;
1129
+ }
1130
+ const start = ++this.position;
1131
+ let depth = 1;
1132
+ while (this.position < this.source.length) {
1133
+ const character = this.source[this.position];
1134
+ if (character === "\\") {
1135
+ this.position += 2;
1136
+ continue;
1137
+ }
1138
+ if (character === "{")
1139
+ depth++;
1140
+ if (character === "}")
1141
+ depth--;
1142
+ if (depth === 0) {
1143
+ const value = this.source.slice(start, this.position);
1144
+ this.position++;
1145
+ return value;
1146
+ }
1147
+ this.position++;
1148
+ }
1149
+ this.supported = false;
1150
+ return undefined;
1151
+ }
1152
+ splitEnvironmentRows(body) {
1153
+ return body.split(/\\\\(?:\[[^\]\n]*\])?/);
1154
+ }
1155
+ parseEnvironment() {
1156
+ const environment = this.readRawGroup();
1157
+ if (!environment) {
1158
+ return "";
1159
+ }
1160
+ const endMarker = `\\end{${environment}}`;
1161
+ const end = this.source.indexOf(endMarker, this.position);
1162
+ if (end < 0) {
1163
+ this.supported = false;
1164
+ return "";
1165
+ }
1166
+ const body = this.source.slice(this.position, end);
1167
+ this.position = end + endMarker.length;
1168
+ if (environment === "equation" || environment === "equation*" || environment === "displaymath") {
1169
+ return this.renderNested(body).trim();
1170
+ }
1171
+ if (environment === "aligned" ||
1172
+ environment === "align" ||
1173
+ environment === "align*" ||
1174
+ environment === "alignedat" ||
1175
+ environment === "alignat" ||
1176
+ environment === "alignat*" ||
1177
+ environment === "gather" ||
1178
+ environment === "gathered" ||
1179
+ environment === "multline" ||
1180
+ environment === "multline*" ||
1181
+ environment === "split") {
1182
+ const alignedAt = ["alignedat", "alignat", "alignat*"].includes(environment);
1183
+ const alignedBody = alignedAt ? body.replace(/^\s*\{[^}]*\}/, "") : body;
1184
+ return this.splitEnvironmentRows(alignedBody)
1185
+ .map((row) => {
1186
+ const cells = row.split("&");
1187
+ const source = alignedAt
1188
+ ? Array.from({ length: Math.ceil(cells.length / 2) }, (_, index) => cells.slice(index * 2, index * 2 + 2).join("")).join(" ")
1189
+ : cells.join("");
1190
+ return this.renderNested(source).trim();
1191
+ })
1192
+ .filter(Boolean)
1193
+ .join("\n");
1194
+ }
1195
+ if (environment === "cases" || environment === "cases*") {
1196
+ const rows = this.splitEnvironmentRows(body)
1197
+ .map((row) => row.split("&").map((cell) => this.renderNested(cell, false).trim()))
1198
+ .filter((row) => row.some(Boolean));
1199
+ return rows
1200
+ .map((row, index) => {
1201
+ const value = (row[0] ?? "").replace(/,\s*$/, "");
1202
+ const condition = row[1] ?? "";
1203
+ const delimiter = index === 0 ? "⎧" : index === rows.length - 1 ? "⎩" : "⎨";
1204
+ const conditionPrefix = /^(?:if|when|for|otherwise)\b/i.test(condition) ? " " : " if ";
1205
+ return `${delimiter} ${value}${condition ? `${conditionPrefix}${condition}` : ""}`;
1206
+ })
1207
+ .join("\n");
1208
+ }
1209
+ if (["array", "matrix", "smallmatrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix"].includes(environment)) {
1210
+ const matrixBody = environment === "array" ? body.replace(/^\s*\{[^}]*\}/, "") : body;
1211
+ return this.renderMatrix(environment, matrixBody);
1212
+ }
1213
+ this.supported = false;
1214
+ return body;
1215
+ }
1216
+ renderMatrix(environment, body) {
1217
+ const matrix = this.splitEnvironmentRows(body)
1218
+ .map((row) => row.split("&").map((cell) => this.renderNested(cell, false).trim()))
1219
+ .filter((row) => row.some(Boolean));
1220
+ const columnCount = Math.max(0, ...matrix.map((row) => row.length));
1221
+ const columnWidths = Array.from({ length: columnCount }, (_, column) => Math.max(0, ...matrix.map((row) => visibleWidth(row[column] ?? ""))));
1222
+ const rows = matrix.map((row) => Array.from({ length: columnCount }, (_, column) => {
1223
+ const cell = row[column] ?? "";
1224
+ return `${cell}${PROTECTED_SPACE.repeat(Math.max(0, (columnWidths[column] ?? 0) - visibleWidth(cell)))}`;
1225
+ }).join(" │ "));
1226
+ let lines;
1227
+ if (environment === "array" || environment === "matrix" || environment === "smallmatrix") {
1228
+ lines = rows;
1229
+ }
1230
+ else {
1231
+ const delimiters = {
1232
+ pmatrix: ["⎛", "⎞", "⎜", "⎟", "⎝", "⎠"],
1233
+ bmatrix: ["⎡", "⎤", "⎢", "⎥", "⎣", "⎦"],
1234
+ Bmatrix: ["⎧", "⎫", "⎨", "⎬", "⎩", "⎭"],
1235
+ vmatrix: ["│", "│", "│", "│", "│", "│"],
1236
+ Vmatrix: ["║", "║", "║", "║", "║", "║"],
1237
+ };
1238
+ const delimiter = delimiters[environment];
1239
+ if (!delimiter) {
1240
+ this.supported = false;
1241
+ return rows.join("\n");
1242
+ }
1243
+ lines = rows.map((row, index) => {
1244
+ const left = index === 0 ? delimiter[0] : index === rows.length - 1 ? delimiter[4] : delimiter[2];
1245
+ const right = index === 0 ? delimiter[1] : index === rows.length - 1 ? delimiter[5] : delimiter[3];
1246
+ return `${left} ${row} ${right}`;
1247
+ });
1248
+ }
1249
+ if (lines.length <= 1) {
1250
+ return lines[0] ?? "";
1251
+ }
1252
+ const index = this.layoutNodes.push({ type: "matrix", lines, baseline: 0 }) - 1;
1253
+ return `${LAYOUT_MARKER_START}${index}${LAYOUT_MARKER_END}`;
1254
+ }
1255
+ renderNested(source, stackFractions = true) {
1256
+ const rendered = new LatexParser(source, this.layoutNodes, this.display && stackFractions).render();
1257
+ if (rendered === undefined) {
1258
+ this.supported = false;
1259
+ return source;
1260
+ }
1261
+ return rendered;
1262
+ }
1263
+ }
1264
+ /**
1265
+ * Render a basic LaTeX math expression as terminal-friendly Unicode text.
1266
+ * Returns undefined when the expression contains unsupported or malformed syntax.
1267
+ */
1268
+ export function renderLatex(source, options = {}) {
1269
+ const layoutNodes = [];
1270
+ const rendered = new LatexParser(source, layoutNodes, options.display === true).render();
1271
+ if (rendered === undefined) {
1272
+ return undefined;
1273
+ }
1274
+ if (layoutNodes.length === 0) {
1275
+ return rendered.replaceAll(PROTECTED_SPACE, " ");
1276
+ }
1277
+ const lines = renderLayout(rendered, layoutNodes).lines;
1278
+ const indentation = Math.min(...lines.filter((line) => line.trim()).map((line) => line.length - line.trimStart().length));
1279
+ return lines
1280
+ .map((line) => line.slice(indentation).trimEnd())
1281
+ .join("\n")
1282
+ .trimEnd()
1283
+ .replaceAll(PROTECTED_SPACE, " ");
1284
+ }
1285
+ //# sourceMappingURL=latex.js.map