katex4arabic 1.1.1
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/LICENSE +21 -0
- package/README.md +303 -0
- package/dist/cdn/katex-arabic.min.cjs +258 -0
- package/dist/cdn/katex-arabic.min.css +9 -0
- package/dist/cdn/katex-arabic.min.js +258 -0
- package/dist/cdn/katex-arabic.min.mjs +11878 -0
- package/dist/lib/arabicFunctions.d.ts +87 -0
- package/dist/lib/arabicFunctions.d.ts.map +1 -0
- package/dist/lib/arabicNumerals.d.ts +50 -0
- package/dist/lib/arabicNumerals.d.ts.map +1 -0
- package/dist/lib/arabicSymbols.d.ts +52 -0
- package/dist/lib/arabicSymbols.d.ts.map +1 -0
- package/dist/lib/cdn.d.ts +18 -0
- package/dist/lib/cdn.d.ts.map +1 -0
- package/dist/lib/hooks.cjs +41 -0
- package/dist/lib/hooks.cjs.map +1 -0
- package/dist/lib/hooks.d.cts +61 -0
- package/dist/lib/hooks.d.ts +61 -0
- package/dist/lib/hooks.d.ts.map +1 -0
- package/dist/lib/hooks.mjs +41 -0
- package/dist/lib/hooks.mjs.map +1 -0
- package/dist/lib/index.cjs +71 -0
- package/dist/lib/index.cjs.map +1 -0
- package/dist/lib/index.d.cts +53 -0
- package/dist/lib/index.d.ts +53 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.mjs +72 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/katex-arabic.css +458 -0
- package/dist/lib/protectedRegions.d.ts +26 -0
- package/dist/lib/protectedRegions.d.ts.map +1 -0
- package/dist/lib/render.cjs +811 -0
- package/dist/lib/render.cjs.map +1 -0
- package/dist/lib/render.d.ts +65 -0
- package/dist/lib/render.d.ts.map +1 -0
- package/dist/lib/render.mjs +812 -0
- package/dist/lib/render.mjs.map +1 -0
- package/dist/lib/rtlRenderer.d.ts +100 -0
- package/dist/lib/rtlRenderer.d.ts.map +1 -0
- package/dist/lib/types.d.ts +98 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/docs/INSTALL.md +314 -0
- package/package.json +119 -0
|
@@ -0,0 +1,811 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const katex = require("katex");
|
|
3
|
+
const ARABIC_INDIC = ["٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"];
|
|
4
|
+
const EXTENDED_ARABIC = ["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"];
|
|
5
|
+
const DIGIT_MAP = {
|
|
6
|
+
arabic: ARABIC_INDIC,
|
|
7
|
+
extended: EXTENDED_ARABIC
|
|
8
|
+
};
|
|
9
|
+
function toArabicNumerals(input, style = "arabic") {
|
|
10
|
+
if (style === "latin") return String(input);
|
|
11
|
+
const digits = DIGIT_MAP[style];
|
|
12
|
+
return String(input).replace(/[0-9]/g, (d) => digits[Number(d)]);
|
|
13
|
+
}
|
|
14
|
+
function fromArabicNumerals(input) {
|
|
15
|
+
return String(input).replace(/[٠-٩]/g, (d) => String(ARABIC_INDIC.indexOf(d))).replace(/[۰-۹]/g, (d) => String(EXTENDED_ARABIC.indexOf(d)));
|
|
16
|
+
}
|
|
17
|
+
function formatArabicNumber(numStr) {
|
|
18
|
+
return numStr.replace(/,/g, "٬").replace(/\./g, "٫").replace(/[0-9]/g, (d) => ARABIC_INDIC[Number(d)]);
|
|
19
|
+
}
|
|
20
|
+
function convertNumbersInText(text, style = "arabic", formatSeparators = true) {
|
|
21
|
+
if (style === "latin") return text;
|
|
22
|
+
return text.replace(/\d+(?:[.,]\d+)*/g, (match) => {
|
|
23
|
+
if (formatSeparators) {
|
|
24
|
+
return formatArabicNumber(match);
|
|
25
|
+
}
|
|
26
|
+
return toArabicNumerals(match, style);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function isArabicDigit(ch) {
|
|
30
|
+
return /[٠-٩۰-۹]/.test(ch);
|
|
31
|
+
}
|
|
32
|
+
const VERBATIM_MACROS = [
|
|
33
|
+
"text",
|
|
34
|
+
"textnormal",
|
|
35
|
+
"textbf",
|
|
36
|
+
"textit",
|
|
37
|
+
"textrm",
|
|
38
|
+
"mathrm",
|
|
39
|
+
"mathbf",
|
|
40
|
+
"mathit",
|
|
41
|
+
"mathtt",
|
|
42
|
+
"mathsf",
|
|
43
|
+
"mathscr",
|
|
44
|
+
"mathfrak",
|
|
45
|
+
"mathbb",
|
|
46
|
+
"mathcal",
|
|
47
|
+
"color",
|
|
48
|
+
"textcolor",
|
|
49
|
+
"operatorname",
|
|
50
|
+
"operatorname*",
|
|
51
|
+
"operatornamewithlimits"
|
|
52
|
+
];
|
|
53
|
+
const VERBATIM_PATTERN = new RegExp(
|
|
54
|
+
`\\\\(?:${VERBATIM_MACROS.join("|")})\\{[^}]*\\}`,
|
|
55
|
+
"g"
|
|
56
|
+
);
|
|
57
|
+
function collectProtectedRegions(latex) {
|
|
58
|
+
const regions = [];
|
|
59
|
+
let m;
|
|
60
|
+
VERBATIM_PATTERN.lastIndex = 0;
|
|
61
|
+
while ((m = VERBATIM_PATTERN.exec(latex)) !== null) {
|
|
62
|
+
regions.push({ start: m.index, end: m.index + m[0].length });
|
|
63
|
+
}
|
|
64
|
+
regions.sort((a, b) => a.start - b.start);
|
|
65
|
+
const merged = [];
|
|
66
|
+
for (const r of regions) {
|
|
67
|
+
const last = merged[merged.length - 1];
|
|
68
|
+
if (last && r.start <= last.end) {
|
|
69
|
+
last.end = Math.max(last.end, r.end);
|
|
70
|
+
} else {
|
|
71
|
+
merged.push({ ...r });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return merged;
|
|
75
|
+
}
|
|
76
|
+
function isInsideRegions(pos, regions) {
|
|
77
|
+
for (const r of regions) {
|
|
78
|
+
if (pos >= r.start && pos < r.end) return true;
|
|
79
|
+
if (r.start > pos) break;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const FUNCTION_MAP = {
|
|
84
|
+
// ─── Basic trigonometric ─────────────────────────────────
|
|
85
|
+
"\\sin": "\\operatorname{جا}",
|
|
86
|
+
"\\cos": "\\operatorname{جتا}",
|
|
87
|
+
"\\tan": "\\operatorname{ظا}",
|
|
88
|
+
"\\cot": "\\operatorname{ظتا}",
|
|
89
|
+
"\\sec": "\\operatorname{قا}",
|
|
90
|
+
"\\csc": "\\operatorname{قتا}",
|
|
91
|
+
// ─── Inverse trigonometric ───────────────────────────────
|
|
92
|
+
"\\arcsin": "\\operatorname{جا}^{-1}",
|
|
93
|
+
"\\arccos": "\\operatorname{جتا}^{-1}",
|
|
94
|
+
"\\arctan": "\\operatorname{ظا}^{-1}",
|
|
95
|
+
"\\arccot": "\\operatorname{ظتا}^{-1}",
|
|
96
|
+
"\\arcsec": "\\operatorname{قا}^{-1}",
|
|
97
|
+
"\\arccsc": "\\operatorname{قتا}^{-1}",
|
|
98
|
+
// ─── Hyperbolic ──────────────────────────────────────────
|
|
99
|
+
"\\sinh": "\\operatorname{جـا}",
|
|
100
|
+
// جيب زائدي
|
|
101
|
+
"\\cosh": "\\operatorname{جتـا}",
|
|
102
|
+
// جيب تمام زائدي
|
|
103
|
+
"\\tanh": "\\operatorname{ظـا}",
|
|
104
|
+
// ظل زائدي
|
|
105
|
+
"\\coth": "\\operatorname{ظتـا}",
|
|
106
|
+
// ظل تمام زائدي
|
|
107
|
+
"\\sech": "\\operatorname{قـا}",
|
|
108
|
+
// قاطع زائدي
|
|
109
|
+
"\\csch": "\\operatorname{قتـا}",
|
|
110
|
+
// قاطع تمام زائدي
|
|
111
|
+
// ─── Logarithms & exponentials ───────────────────────────
|
|
112
|
+
"\\ln": "\\operatorname{لو}",
|
|
113
|
+
"\\log": "\\operatorname{لغ}",
|
|
114
|
+
"\\lg": "\\operatorname{لغ}",
|
|
115
|
+
// ─── Limits (kept as \arabiLim; translated separately) ───
|
|
116
|
+
"\\liminf": "\\operatorname*{نها}",
|
|
117
|
+
// ─── Maxima / minima ─────────────────────────────────────
|
|
118
|
+
"\\max": "\\operatorname*{أقصى}",
|
|
119
|
+
"\\min": "\\operatorname*{أدنى}",
|
|
120
|
+
"\\sup": "\\operatorname*{حد\\,أعلى}",
|
|
121
|
+
"\\inf": "\\operatorname*{حد\\,أدنى}",
|
|
122
|
+
// ─── Linear algebra ──────────────────────────────────────
|
|
123
|
+
"\\det": "\\operatorname{محدد}",
|
|
124
|
+
"\\dim": "\\operatorname{بعد}",
|
|
125
|
+
"\\ker": "\\operatorname{نواة}",
|
|
126
|
+
"\\rank": "\\operatorname{رتبة}",
|
|
127
|
+
"\\tr": "\\operatorname{أثر}",
|
|
128
|
+
"\\diag": "\\operatorname{قطري}",
|
|
129
|
+
"\\span": "\\operatorname{مدى}",
|
|
130
|
+
"\\null": "\\operatorname{فضاء\\,صفري}",
|
|
131
|
+
// ─── Number theory ───────────────────────────────────────
|
|
132
|
+
"\\gcd": "\\operatorname{ق.م.أ}",
|
|
133
|
+
"\\lcm": "\\operatorname{م.م.أ}",
|
|
134
|
+
"\\mod": "\\operatorname{باقي}",
|
|
135
|
+
"\\bmod": "\\operatorname{باقي}",
|
|
136
|
+
// ─── Probability & statistics ────────────────────────────
|
|
137
|
+
"\\Pr": "\\operatorname{حا}",
|
|
138
|
+
"\\P": "\\operatorname{حا}",
|
|
139
|
+
// ─── Complex & argument ──────────────────────────────────
|
|
140
|
+
"\\arg": "\\operatorname{سعة}",
|
|
141
|
+
"\\deg": "\\operatorname{درجة}",
|
|
142
|
+
"\\sgn": "\\operatorname{إشا}",
|
|
143
|
+
"\\Re": "\\operatorname{حق}",
|
|
144
|
+
"\\Im": "\\operatorname{تخ}",
|
|
145
|
+
"\\hom": "\\operatorname{تشا}",
|
|
146
|
+
"\\Hom": "\\operatorname{تشا}",
|
|
147
|
+
// ─── Special operator forms (preserved as-is) ────────────
|
|
148
|
+
// \sum, \prod, \int stay — they are mirrored visually via CSS.
|
|
149
|
+
"\\sum": "\\sum",
|
|
150
|
+
"\\prod": "\\prod",
|
|
151
|
+
"\\coprod": "\\coprod",
|
|
152
|
+
"\\int": "\\int",
|
|
153
|
+
"\\iint": "\\iint",
|
|
154
|
+
"\\iiint": "\\iiint",
|
|
155
|
+
"\\oint": "\\oint",
|
|
156
|
+
"\\partial": "\\partial",
|
|
157
|
+
"\\nabla": "\\nabla",
|
|
158
|
+
"\\infty": "\\infty",
|
|
159
|
+
"\\lim": "\\lim",
|
|
160
|
+
// processed via arabiLim pathway
|
|
161
|
+
"\\limsup": "\\operatorname*{نها}",
|
|
162
|
+
// ─── Special marker used internally for limit translation ─
|
|
163
|
+
// \arabiLim is a sentinel that the translator pipeline replaces
|
|
164
|
+
// with the proper \operatorname* form. Users normally do not write this.
|
|
165
|
+
"\\arabiLim": "\\operatorname*{نها}"
|
|
166
|
+
// '\\lim': '\\operatorname*{نها}',
|
|
167
|
+
};
|
|
168
|
+
const VARIABLE_MAP = {
|
|
169
|
+
// ─── Lowercase ───────────────────────────────────────────
|
|
170
|
+
x: "س",
|
|
171
|
+
y: "ص",
|
|
172
|
+
z: "ع",
|
|
173
|
+
a: "أ",
|
|
174
|
+
b: "ب",
|
|
175
|
+
c: "جـ",
|
|
176
|
+
d: "د",
|
|
177
|
+
e: "هـ",
|
|
178
|
+
// Euler's number
|
|
179
|
+
f: "ف",
|
|
180
|
+
g: "ق",
|
|
181
|
+
h: "ح",
|
|
182
|
+
i: "ت",
|
|
183
|
+
// imaginary unit
|
|
184
|
+
j: "ج",
|
|
185
|
+
k: "ك",
|
|
186
|
+
l: "ل",
|
|
187
|
+
m: "م",
|
|
188
|
+
n: "ن",
|
|
189
|
+
o: "ع",
|
|
190
|
+
p: "ب",
|
|
191
|
+
q: "ق",
|
|
192
|
+
r: "ر",
|
|
193
|
+
s: "ز",
|
|
194
|
+
t: "ت",
|
|
195
|
+
// u: 'ث',
|
|
196
|
+
// v: 'ڤ',
|
|
197
|
+
// w: 'و',
|
|
198
|
+
// ─── Uppercase ───────────────────────────────────────────
|
|
199
|
+
A: "أ",
|
|
200
|
+
B: "ب",
|
|
201
|
+
C: "جـ",
|
|
202
|
+
D: "د",
|
|
203
|
+
E: "هـ",
|
|
204
|
+
F: "ف",
|
|
205
|
+
G: "ق",
|
|
206
|
+
H: "ح",
|
|
207
|
+
I: "ت",
|
|
208
|
+
J: "ج",
|
|
209
|
+
K: "ك",
|
|
210
|
+
L: "ل",
|
|
211
|
+
M: "م",
|
|
212
|
+
N: "ن",
|
|
213
|
+
O: "ع",
|
|
214
|
+
P: "ح",
|
|
215
|
+
Q: "ق",
|
|
216
|
+
R: "ر",
|
|
217
|
+
S: "ز",
|
|
218
|
+
T: "ت",
|
|
219
|
+
U: "ث",
|
|
220
|
+
V: "ڤ",
|
|
221
|
+
W: "و",
|
|
222
|
+
X: "س",
|
|
223
|
+
Y: "ص",
|
|
224
|
+
Z: "ز"
|
|
225
|
+
};
|
|
226
|
+
const GREEK_MAP = {
|
|
227
|
+
"\\alpha": "α",
|
|
228
|
+
"\\beta": "β",
|
|
229
|
+
"\\gamma": "γ",
|
|
230
|
+
"\\delta": "δ",
|
|
231
|
+
"\\epsilon": "ε",
|
|
232
|
+
"\\varepsilon": "ε",
|
|
233
|
+
"\\zeta": "ζ",
|
|
234
|
+
"\\eta": "η",
|
|
235
|
+
"\\theta": "θ",
|
|
236
|
+
"\\vartheta": "ϑ",
|
|
237
|
+
"\\iota": "ι",
|
|
238
|
+
"\\kappa": "κ",
|
|
239
|
+
"\\lambda": "λ",
|
|
240
|
+
"\\mu": "μ",
|
|
241
|
+
"\\nu": "ν",
|
|
242
|
+
"\\xi": "ξ",
|
|
243
|
+
"\\pi": "π",
|
|
244
|
+
"\\varpi": "ϖ",
|
|
245
|
+
"\\rho": "ρ",
|
|
246
|
+
"\\varrho": "ϱ",
|
|
247
|
+
"\\sigma": "σ",
|
|
248
|
+
"\\varsigma": "ς",
|
|
249
|
+
"\\tau": "τ",
|
|
250
|
+
"\\upsilon": "υ",
|
|
251
|
+
"\\phi": "φ",
|
|
252
|
+
"\\varphi": "ϕ",
|
|
253
|
+
"\\chi": "χ",
|
|
254
|
+
"\\psi": "ψ",
|
|
255
|
+
"\\omega": "ω",
|
|
256
|
+
"\\Gamma": "Γ",
|
|
257
|
+
"\\Delta": "Δ",
|
|
258
|
+
"\\Theta": "Θ",
|
|
259
|
+
"\\Lambda": "Λ",
|
|
260
|
+
"\\Xi": "Ξ",
|
|
261
|
+
"\\Pi": "Π",
|
|
262
|
+
"\\Sigma": "Σ",
|
|
263
|
+
"\\Upsilon": "Υ",
|
|
264
|
+
"\\Phi": "Φ",
|
|
265
|
+
"\\Psi": "Ψ",
|
|
266
|
+
"\\Omega": "Ω"
|
|
267
|
+
};
|
|
268
|
+
const DIFFERENTIAL_PATTERNS = {
|
|
269
|
+
dx: "\\text{د}\\text{س}",
|
|
270
|
+
dy: "\\text{د}\\text{ص}",
|
|
271
|
+
dz: "\\text{د}\\text{ع}",
|
|
272
|
+
dt: "\\text{د}\\text{ز}",
|
|
273
|
+
dr: "\\text{د}\\text{ر}",
|
|
274
|
+
du: "\\text{د}\\text{ث}",
|
|
275
|
+
dv: "\\text{د}\\text{ڤ}",
|
|
276
|
+
ds: "\\text{د}\\text{س}",
|
|
277
|
+
dA: "\\text{د}\\text{أ}",
|
|
278
|
+
dV: "\\text{د}\\text{ح}",
|
|
279
|
+
dS: "\\text{د}\\text{س}"
|
|
280
|
+
};
|
|
281
|
+
function escapeRegex$1(input) {
|
|
282
|
+
return input.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
283
|
+
}
|
|
284
|
+
function translateFunctions(latex, customMap = {}) {
|
|
285
|
+
const merged = { ...FUNCTION_MAP, ...customMap };
|
|
286
|
+
const protectedRegions = collectProtectedRegions(latex);
|
|
287
|
+
const cmdPattern = /\\[a-zA-Z]+/g;
|
|
288
|
+
let result = "";
|
|
289
|
+
let cursor = 0;
|
|
290
|
+
let m;
|
|
291
|
+
while ((m = cmdPattern.exec(latex)) !== null) {
|
|
292
|
+
const command = m[0];
|
|
293
|
+
const end = m.index + command.length;
|
|
294
|
+
const next = latex[end];
|
|
295
|
+
const followedByLetter = !!next && /[A-Za-z]/.test(next);
|
|
296
|
+
const replacement = followedByLetter ? void 0 : merged[command];
|
|
297
|
+
if (replacement !== void 0 && !isInsideRegions(m.index, protectedRegions)) {
|
|
298
|
+
result += latex.slice(cursor, m.index) + replacement;
|
|
299
|
+
cursor = end;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
result += latex.slice(cursor, end);
|
|
303
|
+
cursor = end;
|
|
304
|
+
}
|
|
305
|
+
result += latex.slice(cursor);
|
|
306
|
+
return result;
|
|
307
|
+
}
|
|
308
|
+
function translateDifferentials(latex) {
|
|
309
|
+
let result = latex;
|
|
310
|
+
result = result.replace(
|
|
311
|
+
/\bd([xyztruvs])\b/g,
|
|
312
|
+
(_match, letter) => {
|
|
313
|
+
const arabic = VARIABLE_MAP[letter] ?? letter;
|
|
314
|
+
return `\\text{د}\\text{${arabic}}`;
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
result = result.replace(
|
|
318
|
+
/d\\(theta|phi|rho|alpha|beta|gamma|delta)\b/g,
|
|
319
|
+
(_match, greek) => `\\text{د}\\${greek}`
|
|
320
|
+
);
|
|
321
|
+
result = result.replace(
|
|
322
|
+
/\bd([AVS])\b/g,
|
|
323
|
+
(_match, letter) => {
|
|
324
|
+
const arabic = VARIABLE_MAP[letter] ?? letter;
|
|
325
|
+
return `\\text{د}\\text{${arabic}}`;
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
function translateVariables(latex, customMap = {}) {
|
|
331
|
+
const merged = { ...VARIABLE_MAP, ...customMap };
|
|
332
|
+
const keys = Object.keys(merged);
|
|
333
|
+
if (keys.length === 0) return latex;
|
|
334
|
+
const sorted = keys.sort((a, b) => b.length - a.length);
|
|
335
|
+
const protectedRegions = collectProtectedRegions(latex);
|
|
336
|
+
const pattern = new RegExp(
|
|
337
|
+
`(?<![A-Za-z\\\\])(${sorted.map(escapeRegex$1).join("|")})(?![A-Za-z])`,
|
|
338
|
+
"g"
|
|
339
|
+
);
|
|
340
|
+
return latex.replace(pattern, (match, _p1, offset, _string) => {
|
|
341
|
+
const pos = Number(offset);
|
|
342
|
+
if (isInsideRegions(pos, protectedRegions)) return match;
|
|
343
|
+
return `\\text{${merged[match]}}`;
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
function translateSpecialPatterns(latex) {
|
|
347
|
+
return translateDifferentials(latex);
|
|
348
|
+
}
|
|
349
|
+
function translateAll(latex, options = {}) {
|
|
350
|
+
const {
|
|
351
|
+
functions = true,
|
|
352
|
+
variables = true,
|
|
353
|
+
differentials = true,
|
|
354
|
+
customFunctionMap = {},
|
|
355
|
+
customVariableMap = {}
|
|
356
|
+
} = options;
|
|
357
|
+
let result = latex;
|
|
358
|
+
if (differentials) {
|
|
359
|
+
result = translateDifferentials(result);
|
|
360
|
+
}
|
|
361
|
+
if (functions) {
|
|
362
|
+
result = translateFunctions(result, customFunctionMap);
|
|
363
|
+
}
|
|
364
|
+
if (variables) {
|
|
365
|
+
result = translateVariables(result, customVariableMap);
|
|
366
|
+
}
|
|
367
|
+
return result;
|
|
368
|
+
}
|
|
369
|
+
const COMPARISON_MIRRORS = {
|
|
370
|
+
"<": ">",
|
|
371
|
+
">": "<",
|
|
372
|
+
"\\lt": "\\gt",
|
|
373
|
+
"\\gt": "\\lt",
|
|
374
|
+
"\\leq": "\\geq",
|
|
375
|
+
"\\geq": "\\leq",
|
|
376
|
+
"\\le": "\\ge",
|
|
377
|
+
"\\ge": "\\le",
|
|
378
|
+
"\\leqslant": "\\geqslant",
|
|
379
|
+
"\\geqslant": "\\leqslant",
|
|
380
|
+
"\\lesssim": "\\gtrsim",
|
|
381
|
+
"\\gtrsim": "\\lesssim",
|
|
382
|
+
"\\ll": "\\gg",
|
|
383
|
+
"\\gg": "\\ll",
|
|
384
|
+
"\\nless": "\\ngtr",
|
|
385
|
+
"\\ngtr": "\\nless",
|
|
386
|
+
"\\nleq": "\\ngeq",
|
|
387
|
+
"\\ngeq": "\\nleq"
|
|
388
|
+
};
|
|
389
|
+
const ARROW_MIRRORS = {
|
|
390
|
+
"\\to": "\\gets",
|
|
391
|
+
"\\gets": "\\to",
|
|
392
|
+
"\\rightarrow": "\\leftarrow",
|
|
393
|
+
"\\leftarrow": "\\rightarrow",
|
|
394
|
+
"\\longrightarrow": "\\longleftarrow",
|
|
395
|
+
"\\longleftarrow": "\\longrightarrow",
|
|
396
|
+
"\\Rightarrow": "\\Leftarrow",
|
|
397
|
+
"\\Leftarrow": "\\Rightarrow",
|
|
398
|
+
"\\Longrightarrow": "\\Longleftarrow",
|
|
399
|
+
"\\Longleftarrow": "\\Longrightarrow",
|
|
400
|
+
"\\hookrightarrow": "\\hookleftarrow",
|
|
401
|
+
"\\hookleftarrow": "\\hookrightarrow",
|
|
402
|
+
"\\mapsto": "\\mapsfrom",
|
|
403
|
+
"\\mapsfrom": "\\mapsto",
|
|
404
|
+
"\\rightleftharpoons": "\\leftrightharpoons",
|
|
405
|
+
"\\leftrightharpoons": "\\rightleftharpoons"
|
|
406
|
+
};
|
|
407
|
+
const BRACKET_MIRRORS = {
|
|
408
|
+
"\\langle": "\\rangle",
|
|
409
|
+
"\\rangle": "\\langle",
|
|
410
|
+
"\\lceil": "\\rceil",
|
|
411
|
+
"\\rceil": "\\lceil",
|
|
412
|
+
"\\lfloor": "\\rfloor",
|
|
413
|
+
"\\rfloor": "\\lfloor",
|
|
414
|
+
"\\lbrace": "\\rbrace",
|
|
415
|
+
"\\rbrace": "\\lbrace",
|
|
416
|
+
"\\lbrack": "\\rbrack",
|
|
417
|
+
"\\rbrack": "\\lbrack"
|
|
418
|
+
};
|
|
419
|
+
const BIG_OP_MIRRORS = {
|
|
420
|
+
"\\sum": "\\sum",
|
|
421
|
+
// mirrored via CSS
|
|
422
|
+
"\\prod": "\\prod",
|
|
423
|
+
// mirrored via CSS
|
|
424
|
+
"\\int": "\\int",
|
|
425
|
+
// mirrored via CSS
|
|
426
|
+
"\\iint": "\\iint",
|
|
427
|
+
"\\iiint": "\\iiint",
|
|
428
|
+
"\\oint": "\\oint"
|
|
429
|
+
};
|
|
430
|
+
const MIRRORED_SYMBOLS = {
|
|
431
|
+
...COMPARISON_MIRRORS,
|
|
432
|
+
...ARROW_MIRRORS,
|
|
433
|
+
...BRACKET_MIRRORS,
|
|
434
|
+
...BIG_OP_MIRRORS
|
|
435
|
+
};
|
|
436
|
+
const COMPARISON_SYMBOLS = COMPARISON_MIRRORS;
|
|
437
|
+
const ARROW_SYMBOLS = ARROW_MIRRORS;
|
|
438
|
+
const BRACKET_SYMBOLS = BRACKET_MIRRORS;
|
|
439
|
+
const ARABIC_MATH_UNICODE = {
|
|
440
|
+
alef: "𞸀",
|
|
441
|
+
ba: "𞸁",
|
|
442
|
+
jeem: "𞸂",
|
|
443
|
+
dal: "𞸃",
|
|
444
|
+
waw: "𞸅",
|
|
445
|
+
zain: "𞸆",
|
|
446
|
+
ha: "𞸇",
|
|
447
|
+
tah: "𞸈",
|
|
448
|
+
ya: "𞸉",
|
|
449
|
+
kaf: "𞸊",
|
|
450
|
+
lam: "𞸋",
|
|
451
|
+
meem: "𞸌",
|
|
452
|
+
noon: "𞸍",
|
|
453
|
+
seen: "𞸎",
|
|
454
|
+
ain: "𞸏",
|
|
455
|
+
fa: "𞸐",
|
|
456
|
+
sad: "𞸑",
|
|
457
|
+
qaf: "𞸒",
|
|
458
|
+
ra: "𞸓",
|
|
459
|
+
sheen: "𞸔",
|
|
460
|
+
ta: "𞸕",
|
|
461
|
+
tha: "𞸖",
|
|
462
|
+
kha: "𞸗",
|
|
463
|
+
dhal: "𞸘",
|
|
464
|
+
dad: "𞸙",
|
|
465
|
+
ghayn: "𞸚"
|
|
466
|
+
};
|
|
467
|
+
const SPECIAL_ARABIC_SYMBOLS = {
|
|
468
|
+
arabicFractionSlash: "/",
|
|
469
|
+
integralMaghribi: "\\int"
|
|
470
|
+
// mirrored visually via CSS
|
|
471
|
+
};
|
|
472
|
+
function escapeRegex(input) {
|
|
473
|
+
return input.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
474
|
+
}
|
|
475
|
+
function buildMirrorRegex(key) {
|
|
476
|
+
const escaped = escapeRegex(key);
|
|
477
|
+
if (key.length === 1) {
|
|
478
|
+
return new RegExp(`(?<![A-Za-z\\\\])${escaped}(?![A-Za-z])`, "g");
|
|
479
|
+
}
|
|
480
|
+
return new RegExp(escaped + "(?![A-Za-z])", "g");
|
|
481
|
+
}
|
|
482
|
+
function applyMirroredSymbols(latex, enabled = true) {
|
|
483
|
+
if (!enabled) return latex;
|
|
484
|
+
const sorted = Object.entries(MIRRORED_SYMBOLS).sort(
|
|
485
|
+
(a, b) => b[0].length - a[0].length
|
|
486
|
+
);
|
|
487
|
+
const pattern = new RegExp(
|
|
488
|
+
sorted.map(([key]) => `(?:${buildMirrorRegex(key).source})`).join("|"),
|
|
489
|
+
"g"
|
|
490
|
+
);
|
|
491
|
+
const mirrorByText = new Map(
|
|
492
|
+
sorted.map(([key, value]) => [key, value])
|
|
493
|
+
);
|
|
494
|
+
const protectedRegions = collectProtectedRegions(latex);
|
|
495
|
+
return latex.replace(pattern, (...args) => {
|
|
496
|
+
const match = args[0];
|
|
497
|
+
const offset = args[1];
|
|
498
|
+
if (isInsideRegions(offset, protectedRegions)) return match;
|
|
499
|
+
return mirrorByText.get(match) ?? match;
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
const MAX_INPUT_LENGTH = 2e4;
|
|
503
|
+
const CACHE_CAPACITY = 256;
|
|
504
|
+
class LruCache {
|
|
505
|
+
constructor(capacity) {
|
|
506
|
+
this.capacity = capacity;
|
|
507
|
+
}
|
|
508
|
+
capacity;
|
|
509
|
+
map = /* @__PURE__ */ new Map();
|
|
510
|
+
get(key) {
|
|
511
|
+
const value = this.map.get(key);
|
|
512
|
+
if (value !== void 0) {
|
|
513
|
+
this.map.delete(key);
|
|
514
|
+
this.map.set(key, value);
|
|
515
|
+
}
|
|
516
|
+
return value;
|
|
517
|
+
}
|
|
518
|
+
set(key, value) {
|
|
519
|
+
if (this.map.has(key)) {
|
|
520
|
+
this.map.delete(key);
|
|
521
|
+
} else if (this.map.size >= this.capacity) {
|
|
522
|
+
const firstKey = this.map.keys().next().value;
|
|
523
|
+
if (firstKey !== void 0) this.map.delete(firstKey);
|
|
524
|
+
}
|
|
525
|
+
this.map.set(key, value);
|
|
526
|
+
}
|
|
527
|
+
clear() {
|
|
528
|
+
this.map.clear();
|
|
529
|
+
}
|
|
530
|
+
get size() {
|
|
531
|
+
return this.map.size;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
const renderCache = new LruCache(CACHE_CAPACITY);
|
|
535
|
+
function clearRenderCache() {
|
|
536
|
+
renderCache.clear();
|
|
537
|
+
}
|
|
538
|
+
function buildCacheKey(latex, opts) {
|
|
539
|
+
return [
|
|
540
|
+
latex,
|
|
541
|
+
opts.numerals,
|
|
542
|
+
opts.formatNumbers,
|
|
543
|
+
opts.translateFuncs,
|
|
544
|
+
opts.translateVars,
|
|
545
|
+
opts.translateDiffs,
|
|
546
|
+
JSON.stringify(opts.customFunctionMap),
|
|
547
|
+
JSON.stringify(opts.customVariableMap),
|
|
548
|
+
opts.mirrorSymbols,
|
|
549
|
+
opts.mirrorBigOperators,
|
|
550
|
+
opts.mirrorSqrt,
|
|
551
|
+
opts.mirrorBrackets,
|
|
552
|
+
opts.direction,
|
|
553
|
+
opts.fontFamily,
|
|
554
|
+
opts.displayMode,
|
|
555
|
+
opts.fullArabicMode,
|
|
556
|
+
opts.operatorScale,
|
|
557
|
+
JSON.stringify(opts.macros),
|
|
558
|
+
opts.output,
|
|
559
|
+
String(opts.strict),
|
|
560
|
+
opts.trust,
|
|
561
|
+
opts.minRuleThickness
|
|
562
|
+
].join("|");
|
|
563
|
+
}
|
|
564
|
+
const DEFAULT_OPTIONS = {
|
|
565
|
+
// Numerals
|
|
566
|
+
numerals: "arabic",
|
|
567
|
+
formatNumbers: true,
|
|
568
|
+
// Translation
|
|
569
|
+
translateFuncs: true,
|
|
570
|
+
translateVars: true,
|
|
571
|
+
translateDiffs: true,
|
|
572
|
+
customFunctionMap: {},
|
|
573
|
+
customVariableMap: {},
|
|
574
|
+
// Mirroring
|
|
575
|
+
mirrorSymbols: true,
|
|
576
|
+
mirrorBigOperators: true,
|
|
577
|
+
mirrorSqrt: true,
|
|
578
|
+
mirrorBrackets: true,
|
|
579
|
+
// Rendering
|
|
580
|
+
direction: "rtl",
|
|
581
|
+
fontFamily: "Amiri",
|
|
582
|
+
displayMode: false,
|
|
583
|
+
fullArabicMode: true,
|
|
584
|
+
// 1.05 compensates for the x-height difference between Arabic fonts
|
|
585
|
+
// (Amiri et al.) and KaTeX_Main, so Arabic operator names (جا، جتا…)
|
|
586
|
+
// visually match the size of their Latin counterparts out of the box.
|
|
587
|
+
operatorScale: 1.05,
|
|
588
|
+
// KaTeX
|
|
589
|
+
macros: {},
|
|
590
|
+
throwOnError: false,
|
|
591
|
+
output: "html",
|
|
592
|
+
strict: false,
|
|
593
|
+
trust: false,
|
|
594
|
+
minRuleThickness: 0.04
|
|
595
|
+
};
|
|
596
|
+
function resolveOptions(overrides = {}) {
|
|
597
|
+
return { ...DEFAULT_OPTIONS, ...overrides };
|
|
598
|
+
}
|
|
599
|
+
function processArabicLatex(latex, options = {}) {
|
|
600
|
+
const opts = resolveOptions(options);
|
|
601
|
+
let processed = latex.length > MAX_INPUT_LENGTH ? latex.slice(0, MAX_INPUT_LENGTH) : latex;
|
|
602
|
+
if (!processed.trim()) return processed;
|
|
603
|
+
if (opts.translateFuncs) {
|
|
604
|
+
processed = processed.replace(/\\lim(?![A-Za-z])/g, "\\arabiLim");
|
|
605
|
+
}
|
|
606
|
+
if (opts.translateDiffs) {
|
|
607
|
+
processed = translateDifferentials(processed);
|
|
608
|
+
}
|
|
609
|
+
if (opts.translateFuncs) {
|
|
610
|
+
processed = translateFunctions(processed, opts.customFunctionMap);
|
|
611
|
+
}
|
|
612
|
+
if (opts.translateVars) {
|
|
613
|
+
processed = translateVariables(processed, opts.customVariableMap);
|
|
614
|
+
}
|
|
615
|
+
if (opts.mirrorSymbols) {
|
|
616
|
+
processed = applyMirroredSymbols(processed, true);
|
|
617
|
+
}
|
|
618
|
+
if (opts.numerals !== "latin") {
|
|
619
|
+
processed = convertNumbersInLatex(processed, opts.numerals, opts.formatNumbers);
|
|
620
|
+
}
|
|
621
|
+
return processed;
|
|
622
|
+
}
|
|
623
|
+
function convertNumbersInLatex(latex, style, formatSeparators) {
|
|
624
|
+
let result = "";
|
|
625
|
+
let i = 0;
|
|
626
|
+
while (i < latex.length) {
|
|
627
|
+
const ch = latex[i];
|
|
628
|
+
if (ch && /[0-9]/.test(ch)) {
|
|
629
|
+
const prev = i > 0 ? latex[i - 1] : "";
|
|
630
|
+
if (prev && /[A-Za-z]/.test(prev)) {
|
|
631
|
+
result += ch;
|
|
632
|
+
} else {
|
|
633
|
+
let j = i;
|
|
634
|
+
while (j < latex.length) {
|
|
635
|
+
const cj = latex[j];
|
|
636
|
+
if (cj && /[0-9.,]/.test(cj)) {
|
|
637
|
+
j++;
|
|
638
|
+
} else {
|
|
639
|
+
break;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
const run = latex.slice(i, j);
|
|
643
|
+
result += formatSeparators ? formatArabicNumber(run) : toArabicNumerals(run, style);
|
|
644
|
+
i = j;
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
} else {
|
|
648
|
+
result += ch ?? "";
|
|
649
|
+
}
|
|
650
|
+
i++;
|
|
651
|
+
}
|
|
652
|
+
return result;
|
|
653
|
+
}
|
|
654
|
+
function getArabicMacros(customMacros = {}) {
|
|
655
|
+
return {
|
|
656
|
+
// Trigonometric
|
|
657
|
+
"\\جا": "\\operatorname{جا}",
|
|
658
|
+
"\\جتا": "\\operatorname{جتا}",
|
|
659
|
+
"\\ظا": "\\operatorname{ظا}",
|
|
660
|
+
"\\ظتا": "\\operatorname{ظتا}",
|
|
661
|
+
"\\قا": "\\operatorname{قا}",
|
|
662
|
+
"\\قتا": "\\operatorname{قتا}",
|
|
663
|
+
// Logarithms
|
|
664
|
+
"\\لو": "\\operatorname{لو}",
|
|
665
|
+
"\\لغ": "\\operatorname{لغ}",
|
|
666
|
+
// Limits
|
|
667
|
+
"\\نها": "\\operatorname*{نها}",
|
|
668
|
+
"\\نهى": "\\operatorname*{نها}",
|
|
669
|
+
// Max/min
|
|
670
|
+
"\\اقصى": "\\operatorname*{أقصى}",
|
|
671
|
+
"\\ادنى": "\\operatorname*{أدنى}",
|
|
672
|
+
// Imaginary / constants
|
|
673
|
+
"\\ت": "\\text{ت}",
|
|
674
|
+
"\\هـ": "\\text{هـ}",
|
|
675
|
+
...customMacros
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
function buildCssClasses(options) {
|
|
679
|
+
const opts = resolveOptions(options);
|
|
680
|
+
const classes = ["katex-arabic"];
|
|
681
|
+
if (opts.mirrorBigOperators) classes.push("mirror-big-ops");
|
|
682
|
+
if (opts.mirrorSqrt) classes.push("mirror-sqrt");
|
|
683
|
+
if (opts.mirrorBrackets) classes.push("mirror-brackets");
|
|
684
|
+
if (opts.mirrorSymbols) classes.push("mirror-symbols");
|
|
685
|
+
if (opts.fullArabicMode) classes.push("full-rtl-mode");
|
|
686
|
+
if (opts.displayMode) classes.push("is-display");
|
|
687
|
+
else classes.push("is-inline");
|
|
688
|
+
return classes;
|
|
689
|
+
}
|
|
690
|
+
function wrapWithArabicStyles(html, options) {
|
|
691
|
+
const opts = resolveOptions(options);
|
|
692
|
+
const classes = buildCssClasses(opts);
|
|
693
|
+
return `<span class="${classes.join(" ")}" dir="${opts.direction}" style="font-family:'${opts.fontFamily}','KaTeX_Main',serif;direction:${opts.direction};--ka-op-scale:${opts.operatorScale};">${html}</span>`;
|
|
694
|
+
}
|
|
695
|
+
function escapeHtml(text) {
|
|
696
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
697
|
+
}
|
|
698
|
+
function renderArabicToString(latex, options = {}) {
|
|
699
|
+
return renderArabicWithMeta(latex, options).html;
|
|
700
|
+
}
|
|
701
|
+
function renderArabicWithMeta(latex, options = {}) {
|
|
702
|
+
const opts = resolveOptions(options);
|
|
703
|
+
const cacheKey = buildCacheKey(latex, opts);
|
|
704
|
+
const cached = renderCache.get(cacheKey);
|
|
705
|
+
if (cached !== void 0) {
|
|
706
|
+
return { html: cached, error: null };
|
|
707
|
+
}
|
|
708
|
+
const processedLatex = processArabicLatex(latex, opts);
|
|
709
|
+
try {
|
|
710
|
+
const html = katex.renderToString(processedLatex, {
|
|
711
|
+
displayMode: opts.displayMode,
|
|
712
|
+
throwOnError: true,
|
|
713
|
+
output: opts.output,
|
|
714
|
+
strict: opts.strict,
|
|
715
|
+
trust: opts.trust,
|
|
716
|
+
minRuleThickness: opts.minRuleThickness,
|
|
717
|
+
macros: {
|
|
718
|
+
...getArabicMacros(opts.macros),
|
|
719
|
+
...opts.macros ?? {}
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
const wrapped = wrapWithArabicStyles(html, opts);
|
|
723
|
+
renderCache.set(cacheKey, wrapped);
|
|
724
|
+
return { html: wrapped, error: null };
|
|
725
|
+
} catch (error) {
|
|
726
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
727
|
+
if (opts.throwOnError) {
|
|
728
|
+
throw error instanceof Error ? error : new Error(message);
|
|
729
|
+
}
|
|
730
|
+
console.error("[katex-arabic] render failed:", message, "\nLaTeX:", latex);
|
|
731
|
+
return {
|
|
732
|
+
html: `<span class="katex-arabic katex-arabic--error" dir="rtl" role="alert" style="color:#dc2626;font-family:monospace;"><span class="katex-arabic__error-icon" aria-hidden="true">⚠</span> <span class="katex-arabic__error-text">${escapeHtml(latex)}</span></span>`,
|
|
733
|
+
error: message
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
function renderArabic(latex, element, options = {}) {
|
|
738
|
+
const html = renderArabicToString(latex, options);
|
|
739
|
+
element.innerHTML = html;
|
|
740
|
+
applyDomStyles(element, options);
|
|
741
|
+
}
|
|
742
|
+
function renderArabicBatch(items, options = {}) {
|
|
743
|
+
return items.map((item) => {
|
|
744
|
+
if (typeof item === "string") {
|
|
745
|
+
return renderArabicWithMeta(item, options);
|
|
746
|
+
}
|
|
747
|
+
return renderArabicWithMeta(item.latex, { ...options, ...item.options });
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
function processLatex(latex, options = {}) {
|
|
751
|
+
return processArabicLatex(latex, options);
|
|
752
|
+
}
|
|
753
|
+
function validateLatex(latex, options = {}) {
|
|
754
|
+
const opts = resolveOptions(options);
|
|
755
|
+
const processed = processArabicLatex(latex, opts);
|
|
756
|
+
try {
|
|
757
|
+
katex.renderToString(processed, {
|
|
758
|
+
displayMode: opts.displayMode,
|
|
759
|
+
throwOnError: true,
|
|
760
|
+
strict: opts.strict,
|
|
761
|
+
trust: opts.trust
|
|
762
|
+
});
|
|
763
|
+
return null;
|
|
764
|
+
} catch (error) {
|
|
765
|
+
return error instanceof Error ? error.message : String(error);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
function applyDomStyles(element, options) {
|
|
769
|
+
const opts = resolveOptions(options);
|
|
770
|
+
const katexEl = element.querySelector(".katex");
|
|
771
|
+
if (katexEl) {
|
|
772
|
+
katexEl.setAttribute("dir", opts.direction);
|
|
773
|
+
katexEl.style.fontFamily = `'${opts.fontFamily}', 'KaTeX_Main', serif`;
|
|
774
|
+
katexEl.style.direction = opts.direction;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
exports.ARABIC_MATH_UNICODE = ARABIC_MATH_UNICODE;
|
|
778
|
+
exports.ARROW_SYMBOLS = ARROW_SYMBOLS;
|
|
779
|
+
exports.BRACKET_SYMBOLS = BRACKET_SYMBOLS;
|
|
780
|
+
exports.COMPARISON_SYMBOLS = COMPARISON_SYMBOLS;
|
|
781
|
+
exports.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
|
|
782
|
+
exports.DIFFERENTIAL_PATTERNS = DIFFERENTIAL_PATTERNS;
|
|
783
|
+
exports.FUNCTION_MAP = FUNCTION_MAP;
|
|
784
|
+
exports.GREEK_MAP = GREEK_MAP;
|
|
785
|
+
exports.MAX_INPUT_LENGTH = MAX_INPUT_LENGTH;
|
|
786
|
+
exports.MIRRORED_SYMBOLS = MIRRORED_SYMBOLS;
|
|
787
|
+
exports.SPECIAL_ARABIC_SYMBOLS = SPECIAL_ARABIC_SYMBOLS;
|
|
788
|
+
exports.VARIABLE_MAP = VARIABLE_MAP;
|
|
789
|
+
exports.applyMirroredSymbols = applyMirroredSymbols;
|
|
790
|
+
exports.buildCssClasses = buildCssClasses;
|
|
791
|
+
exports.clearRenderCache = clearRenderCache;
|
|
792
|
+
exports.convertNumbersInText = convertNumbersInText;
|
|
793
|
+
exports.formatArabicNumber = formatArabicNumber;
|
|
794
|
+
exports.fromArabicNumerals = fromArabicNumerals;
|
|
795
|
+
exports.getArabicMacros = getArabicMacros;
|
|
796
|
+
exports.isArabicDigit = isArabicDigit;
|
|
797
|
+
exports.processArabicLatex = processArabicLatex;
|
|
798
|
+
exports.processLatex = processLatex;
|
|
799
|
+
exports.renderArabic = renderArabic;
|
|
800
|
+
exports.renderArabicBatch = renderArabicBatch;
|
|
801
|
+
exports.renderArabicToString = renderArabicToString;
|
|
802
|
+
exports.renderArabicWithMeta = renderArabicWithMeta;
|
|
803
|
+
exports.resolveOptions = resolveOptions;
|
|
804
|
+
exports.toArabicNumerals = toArabicNumerals;
|
|
805
|
+
exports.translateAll = translateAll;
|
|
806
|
+
exports.translateDifferentials = translateDifferentials;
|
|
807
|
+
exports.translateFunctions = translateFunctions;
|
|
808
|
+
exports.translateSpecialPatterns = translateSpecialPatterns;
|
|
809
|
+
exports.translateVariables = translateVariables;
|
|
810
|
+
exports.validateLatex = validateLatex;
|
|
811
|
+
//# sourceMappingURL=render.cjs.map
|