@drghaliasri/butex 5.5.4 → 5.6.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.
@@ -48,21 +48,26 @@ var BUTEX_CLOSING_HAMDALA = "\u0627\u0644\u0652\u062D\u064E\u0645\u0652\u062F\u0
48
48
  function escapeButexTextArg(text) {
49
49
  return text.replace(/\\/g, "\\textbackslash{}").replace(/[{}]/g, "\\$&");
50
50
  }
51
- function butexDiwaniDisplayTex(text) {
52
- return `\\butexdiwani{${escapeButexTextArg(text)}}`;
51
+ function butexFontDisplayTex(macro, text) {
52
+ return `${macro}{${escapeButexTextArg(text)}}`;
53
53
  }
54
- function butexDiwaniDisplayLatex(text) {
54
+ function butexMaghribiDisplayTex(text) {
55
+ return butexFontDisplayTex("\\butexmaghribi", text);
56
+ }
57
+ function butexMaghribiDisplayLatex(text) {
55
58
  return `\\[
56
- ${butexDiwaniDisplayTex(text)}
59
+ ${butexMaghribiDisplayTex(text)}
57
60
  \\]`;
58
61
  }
59
62
  var BASMALA_LINES = [BUTEX_BASMALA_LINE1, BUTEX_BASMALA_LINE2, BUTEX_BASMALA_SALAWAT];
60
63
  function butexBasmalaDisplayTex() {
61
- return BASMALA_LINES.map((line) => butexDiwaniDisplayTex(line)).join(" \\\\ ");
64
+ return BASMALA_LINES.map((line) => butexMaghribiDisplayTex(line)).join(" \\\\ ");
62
65
  }
63
66
  function butexBasmalaDisplayLatex() {
64
67
  return `\\[
65
- ${butexBasmalaDisplayTex()}
68
+ \\begin{gathered}
69
+ ${BASMALA_LINES.map((line) => butexMaghribiDisplayTex(line)).join(" \\\\\n")}
70
+ \\end{gathered}
66
71
  \\]`;
67
72
  }
68
73
  function butexInColumnMaketitleHook() {
@@ -99,7 +104,7 @@ function butexBasmalaTitlingPreamble(options = {}) {
99
104
  " \\begin{center}",
100
105
  ...BASMALA_LINES.map((line, index) => {
101
106
  const suffix = index < BASMALA_LINES.length - 1 ? "\\\\" : "";
102
- return ` ${butexDiwaniDisplayTex(line)}${suffix}`;
107
+ return ` ${butexMaghribiDisplayTex(line)}${suffix}`;
103
108
  }),
104
109
  " \\par\\vspace{1.5em}",
105
110
  " \\LARGE",
@@ -2064,6 +2069,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2064
2069
  category: "operators1",
2065
2070
  Tex: "\\neq",
2066
2071
  mirror: true,
2072
+ compileMirror: true,
2067
2073
  Label: "\u2260",
2068
2074
  title: "\u0644\u0627 \u064A\u0633\u0627\u0648\u064A",
2069
2075
  svg_path: null
@@ -2103,6 +2109,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2103
2109
  Tex: "\\leq",
2104
2110
  mirror: true,
2105
2111
  displayMirror: false,
2112
+ compileMirror: true,
2106
2113
  Label: "\u2264",
2107
2114
  title: "\u0623\u0635\u063A\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
2108
2115
  svg_path: null
@@ -2113,6 +2120,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2113
2120
  Tex: "\\geq",
2114
2121
  mirror: true,
2115
2122
  displayMirror: false,
2123
+ compileMirror: true,
2116
2124
  Label: "\u2265",
2117
2125
  title: "\u0623\u0643\u0628\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
2118
2126
  svg_path: null
@@ -2123,6 +2131,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2123
2131
  Tex: "\\coloneqq",
2124
2132
  mirror: true,
2125
2133
  displayMirror: false,
2134
+ compileMirror: true,
2126
2135
  Label: "\u2254",
2127
2136
  title: "\u064A\u0639\u0631\u0641 \u0628\u0623\u0646\u0647 \u064A\u0633\u0627\u0648\u064A",
2128
2137
  svg_path: null
@@ -2133,6 +2142,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2133
2142
  Tex: "\\eqqcolon",
2134
2143
  mirror: true,
2135
2144
  displayMirror: false,
2145
+ compileMirror: true,
2136
2146
  Label: "\u2255",
2137
2147
  title: "\u064A\u0633\u0627\u0648\u064A \u0628\u0627\u0644\u062A\u0639\u0631\u064A\u0641",
2138
2148
  svg_path: null
@@ -2144,6 +2154,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2144
2154
  Tex: "\\propto",
2145
2155
  mirror: true,
2146
2156
  displayMirror: false,
2157
+ compileMirror: true,
2147
2158
  Label: "\u221D",
2148
2159
  title: "\u064A\u062A\u0646\u0627\u0633\u0628 \u0645\u0639",
2149
2160
  svg_path: null
@@ -2154,6 +2165,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2154
2165
  Tex: "\\in",
2155
2166
  mirror: true,
2156
2167
  displayMirror: false,
2168
+ compileMirror: true,
2157
2169
  Label: "\u2208",
2158
2170
  title: "\u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
2159
2171
  svg_path: null
@@ -2174,6 +2186,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2174
2186
  Tex: "\\subset",
2175
2187
  mirror: true,
2176
2188
  displayMirror: false,
2189
+ compileMirror: true,
2177
2190
  Label: "\u2282",
2178
2191
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0645\u0646",
2179
2192
  svg_path: null
@@ -2184,6 +2197,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2184
2197
  Tex: "\\supset",
2185
2198
  mirror: true,
2186
2199
  displayMirror: false,
2200
+ compileMirror: true,
2187
2201
  Label: "\u2283",
2188
2202
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0644\u0640",
2189
2203
  svg_path: null
@@ -2194,6 +2208,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2194
2208
  Tex: "\\subseteq",
2195
2209
  mirror: true,
2196
2210
  displayMirror: false,
2211
+ compileMirror: true,
2197
2212
  Label: "\u2286",
2198
2213
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
2199
2214
  svg_path: null
@@ -2204,6 +2219,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2204
2219
  Tex: "\\supseteq",
2205
2220
  mirror: true,
2206
2221
  displayMirror: false,
2222
+ compileMirror: true,
2207
2223
  Label: "\u2287",
2208
2224
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
2209
2225
  svg_path: null
@@ -2244,6 +2260,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2244
2260
  Tex: "\\nsubseteq",
2245
2261
  mirror: true,
2246
2262
  displayMirror: false,
2263
+ compileMirror: true,
2247
2264
  Label: "\u2288",
2248
2265
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
2249
2266
  svg_path: null
@@ -2254,6 +2271,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2254
2271
  Tex: "\\nsupseteq",
2255
2272
  mirror: true,
2256
2273
  displayMirror: false,
2274
+ compileMirror: true,
2257
2275
  Label: "\u2289",
2258
2276
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
2259
2277
  svg_path: null
@@ -2301,6 +2319,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2301
2319
  Tex: "\\ddots",
2302
2320
  mirror: true,
2303
2321
  displayMirror: false,
2322
+ compileMirror: true,
2304
2323
  Label: "\u22F1",
2305
2324
  title: "\u0646\u0642\u0627\u0637 \u0642\u0637\u0631\u064A\u0629",
2306
2325
  svg_path: null
@@ -2320,6 +2339,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2320
2339
  category: "operators3",
2321
2340
  Tex: "\\implies",
2322
2341
  mirror: true,
2342
+ compileMirror: true,
2323
2343
  Label: "\u21D2",
2324
2344
  title: "\u064A\u0633\u062A\u0644\u0632\u0645",
2325
2345
  svg_path: null
@@ -2329,6 +2349,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2329
2349
  category: "operators3",
2330
2350
  Tex: "\\impliedby",
2331
2351
  mirror: true,
2352
+ compileMirror: true,
2332
2353
  Label: "\u21D0",
2333
2354
  title: "\u0645\u0633\u062A\u0644\u0632\u0645 \u0645\u0646",
2334
2355
  svg_path: null
@@ -2347,6 +2368,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2347
2368
  category: "operators3",
2348
2369
  Tex: "\\Longrightarrow",
2349
2370
  mirror: true,
2371
+ compileMirror: true,
2350
2372
  Label: "\u27F9",
2351
2373
  title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0637\u0648\u064A\u0644 \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2352
2374
  svg_path: null
@@ -2356,6 +2378,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2356
2378
  category: "operators3",
2357
2379
  Tex: "\\Longleftarrow",
2358
2380
  mirror: true,
2381
+ compileMirror: true,
2359
2382
  Label: "\u27F8",
2360
2383
  title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0637\u0648\u064A\u0644 \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2361
2384
  svg_path: null
@@ -2365,6 +2388,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2365
2388
  category: "operators3",
2366
2389
  Tex: "\\to",
2367
2390
  mirror: true,
2391
+ compileMirror: true,
2368
2392
  Label: "\u2192",
2369
2393
  title: "\u064A\u0624\u0648\u0644 \u0625\u0644\u0649",
2370
2394
  svg_path: null
@@ -2374,6 +2398,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2374
2398
  category: "operators3",
2375
2399
  Tex: "\\rightleftharpoons",
2376
2400
  mirror: true,
2401
+ compileMirror: true,
2377
2402
  Label: "\u21CC",
2378
2403
  title: "\u0627\u062A\u0632\u0627\u0646",
2379
2404
  svg_path: null
@@ -2383,6 +2408,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2383
2408
  category: "operators3",
2384
2409
  Tex: "\\leftarrow",
2385
2410
  mirror: true,
2411
+ compileMirror: true,
2386
2412
  Label: "\u2190",
2387
2413
  title: "\u0633\u0647\u0645 \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2388
2414
  svg_path: null
@@ -2392,6 +2418,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2392
2418
  category: "operators3",
2393
2419
  Tex: "\\rightarrow",
2394
2420
  mirror: true,
2421
+ compileMirror: true,
2395
2422
  Label: "\u2192",
2396
2423
  title: "\u0633\u0647\u0645 \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2397
2424
  svg_path: null
@@ -2401,6 +2428,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2401
2428
  category: "operators3",
2402
2429
  Tex: "\\Leftarrow",
2403
2430
  mirror: true,
2431
+ compileMirror: true,
2404
2432
  Label: "\u21D0",
2405
2433
  title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2406
2434
  svg_path: null
@@ -2410,6 +2438,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2410
2438
  category: "operators3",
2411
2439
  Tex: "\\Rightarrow",
2412
2440
  mirror: true,
2441
+ compileMirror: true,
2413
2442
  Label: "\u21D2",
2414
2443
  title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2415
2444
  svg_path: null
@@ -2419,6 +2448,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2419
2448
  category: "operators3",
2420
2449
  Tex: "\\leftharpoonup",
2421
2450
  mirror: true,
2451
+ compileMirror: true,
2422
2452
  Label: "\u21BC",
2423
2453
  title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2424
2454
  svg_path: null
@@ -2428,6 +2458,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2428
2458
  category: "operators3",
2429
2459
  Tex: "\\rightharpoonup",
2430
2460
  mirror: true,
2461
+ compileMirror: true,
2431
2462
  Label: "\u21C0",
2432
2463
  title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2433
2464
  svg_path: null
@@ -2437,6 +2468,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2437
2468
  category: "operators3",
2438
2469
  Tex: "\\leftharpoondown",
2439
2470
  mirror: true,
2471
+ compileMirror: true,
2440
2472
  Label: "\u21BD",
2441
2473
  title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0633\u0641\u0644\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2442
2474
  svg_path: null
@@ -2446,6 +2478,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2446
2478
  category: "operators3",
2447
2479
  Tex: "\\rightharpoondown",
2448
2480
  mirror: true,
2481
+ compileMirror: true,
2449
2482
  Label: "\u21C1",
2450
2483
  title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0633\u0641\u0644\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2451
2484
  svg_path: null
@@ -2456,6 +2489,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2456
2489
  category: "integrals",
2457
2490
  Tex: "\\int",
2458
2491
  mirror: true,
2492
+ compileMirror: true,
2459
2493
  Label: "\u222B",
2460
2494
  title: "\u062A\u0643\u0627\u0645\u0644",
2461
2495
  svg_path: null
@@ -2466,6 +2500,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2466
2500
  Tex: "\\iint",
2467
2501
  mirror: true,
2468
2502
  displayMirror: false,
2503
+ compileMirror: true,
2469
2504
  Label: "\u222C",
2470
2505
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u0632\u062F\u0648\u062C",
2471
2506
  svg_path: null
@@ -2476,6 +2511,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2476
2511
  Tex: "\\iiint",
2477
2512
  mirror: true,
2478
2513
  displayMirror: false,
2514
+ compileMirror: true,
2479
2515
  Label: "\u222D",
2480
2516
  title: "\u062A\u0643\u0627\u0645\u0644 \u062B\u0644\u0627\u062B\u064A",
2481
2517
  svg_path: null
@@ -2486,6 +2522,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2486
2522
  Tex: "\\iiiint",
2487
2523
  mirror: true,
2488
2524
  displayMirror: false,
2525
+ compileMirror: true,
2489
2526
  Label: "\u2A0C",
2490
2527
  title: "\u062A\u0643\u0627\u0645\u0644 \u0631\u0628\u0627\u0639\u064A",
2491
2528
  svg_path: null
@@ -2496,6 +2533,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2496
2533
  Tex: "\\oint",
2497
2534
  mirror: true,
2498
2535
  displayMirror: false,
2536
+ compileMirror: true,
2499
2537
  Label: "\u222E",
2500
2538
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u063A\u0644\u0642",
2501
2539
  svg_path: null
@@ -2506,6 +2544,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2506
2544
  Tex: "\\oiint",
2507
2545
  mirror: true,
2508
2546
  displayMirror: false,
2547
+ compileMirror: true,
2509
2548
  Label: "\u222F",
2510
2549
  title: "\u062A\u0643\u0627\u0645\u0644 \u0633\u0637\u062D\u064A \u0645\u063A\u0644\u0642",
2511
2550
  svg_path: null
@@ -2516,6 +2555,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2516
2555
  Tex: "\\oiiint",
2517
2556
  mirror: true,
2518
2557
  displayMirror: false,
2558
+ compileMirror: true,
2519
2559
  Label: "\u2230",
2520
2560
  title: "\u062A\u0643\u0627\u0645\u0644 \u062D\u062C\u0645\u064A \u0645\u063A\u0644\u0642",
2521
2561
  svg_path: null
@@ -2525,8 +2565,9 @@ function shouldMirrorOperatorDisplay(command) {
2525
2565
  return command?.displayMirror ?? command?.mirror ?? false;
2526
2566
  }
2527
2567
  var MIRRORED_OPERATOR_TEX = Object.values(ATOMIC_OPERATOR_COMMANDS).filter((command) => command.mirror).map((command) => command.Tex).sort((a, b) => b.length - a.length);
2528
- function matchingMirroredOperator(tex, index) {
2529
- for (const operatorTex of MIRRORED_OPERATOR_TEX) {
2568
+ var COMPILE_MIRRORED_OPERATOR_TEX = Object.values(ATOMIC_OPERATOR_COMMANDS).filter((command) => "compileMirror" in command && command.compileMirror).map((command) => command.Tex).sort((a, b) => b.length - a.length);
2569
+ function matchingMirroredOperatorFrom(tex, index, operatorTexList) {
2570
+ for (const operatorTex of operatorTexList) {
2530
2571
  if (!tex.startsWith(operatorTex, index)) {
2531
2572
  continue;
2532
2573
  }
@@ -2557,19 +2598,26 @@ function findMatchingBrace(tex, openIndex) {
2557
2598
  }
2558
2599
  return -1;
2559
2600
  }
2560
- function mirrorBuTeXOperatorsInTex(tex) {
2601
+ function mirrorBuTeXOperatorsInTex(tex, options = {}) {
2602
+ const mirroredOperatorTex = options.target === "compile" ? COMPILE_MIRRORED_OPERATOR_TEX : MIRRORED_OPERATOR_TEX;
2561
2603
  let result = "";
2562
2604
  let index = 0;
2563
2605
  while (index < tex.length) {
2564
2606
  if (tex.startsWith("\\butexmirror{", index)) {
2565
2607
  const end = findMatchingBrace(tex, index + "\\butexmirror".length);
2566
2608
  if (end !== -1) {
2567
- result += tex.slice(index, end + 1);
2609
+ const bodyStart = index + "\\butexmirror{".length;
2610
+ const body = tex.slice(bodyStart, end);
2611
+ if (options.target === "compile" && MIRRORED_OPERATOR_TEX.includes(body) && !mirroredOperatorTex.includes(body)) {
2612
+ result += body;
2613
+ } else {
2614
+ result += tex.slice(index, end + 1);
2615
+ }
2568
2616
  index = end + 1;
2569
2617
  continue;
2570
2618
  }
2571
2619
  }
2572
- const operatorTex = matchingMirroredOperator(tex, index);
2620
+ const operatorTex = matchingMirroredOperatorFrom(tex, index, mirroredOperatorTex);
2573
2621
  if (operatorTex) {
2574
2622
  result += `\\butexmirror{${operatorTex}}`;
2575
2623
  index += operatorTex.length;
@@ -8231,18 +8279,19 @@ function mathNodeFromSession(session, opening = "$", closing = "$") {
8231
8279
  }
8232
8280
  return { nodeType: "MathObject", mathMode: opening, lines: [], closing };
8233
8281
  }
8234
- function mathTokenSourceForSide(token, side) {
8282
+ function mathTokenSourceForSide(token, side, digitForm) {
8235
8283
  if (!token.math || token.sourceOwner === "raw") {
8236
8284
  return token.source;
8237
8285
  }
8238
- if (token.sourceSide === side) {
8286
+ if (token.sourceSide === side && digitForm === void 0) {
8239
8287
  return token.source;
8240
8288
  }
8241
8289
  const result = mathTokenToEditorSession(token.math, side);
8242
8290
  if (!result.editable) {
8243
8291
  return token.source;
8244
8292
  }
8245
- return mathSourceFromSession(result.session, side, token.opening, token.closing);
8293
+ const session = digitForm === void 0 ? result.session : setCurrentDigitForm(result.session, digitForm);
8294
+ return mathSourceFromSession(session, side, token.opening, token.closing);
8246
8295
  }
8247
8296
 
8248
8297
  // src/document2/commands.ts
@@ -8976,6 +9025,19 @@ function document2KeyError(key, namespace = {}) {
8976
9025
  }
8977
9026
 
8978
9027
  // src/document2/arabicPreamble.ts
9028
+ function fontOptions(digitsMapping, includeScript = true) {
9029
+ const parts = [];
9030
+ if (includeScript) {
9031
+ parts.push("Script=Arabic");
9032
+ }
9033
+ if (digitsMapping !== "digits") {
9034
+ parts.push(`Mapping=${digitsMapping}`);
9035
+ }
9036
+ if (parts.length === 0) {
9037
+ return "";
9038
+ }
9039
+ return `[${parts.join(",")}]`;
9040
+ }
8979
9041
  function arabicXeLatexPreamblePkg(twocolumn = false) {
8980
9042
  const classOptions = twocolumn ? "12pt,a4paper,notitlepage,twocolumn" : "12pt,a4paper,notitlepage";
8981
9043
  return `
@@ -9004,25 +9066,27 @@ function arabicXeLatexPreamblePkg(twocolumn = false) {
9004
9066
  % save back tick for use - copy paste -> ` + "`";
9005
9067
  }
9006
9068
  function arabicXeLatexPreambleFont(digitsMapping = "arabicdigits") {
9007
- const customFonts = NON_DEFAULT_CHARACTER_FONT_SPECS.filter((font) => font.latexFontCommand && font.latexFontFamily).map((font) => `\\newfontfamily${font.latexFontCommand}[Script=Arabic,Mapping=${digitsMapping}]{${font.latexFontFamily}}`).join("\n");
9069
+ const customFonts = NON_DEFAULT_CHARACTER_FONT_SPECS.filter((font) => font.latexFontCommand && font.latexFontFamily).map((font) => `\\newfontfamily${font.latexFontCommand}${fontOptions(digitsMapping)}{${font.latexFontFamily}}`).join("\n");
9070
+ const mathFontOptions = fontOptions(digitsMapping, false);
9008
9071
  return `
9009
9072
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9010
9073
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9011
- % Toggle between eastern and western digits by changing the Mapping in the below fonts (inside math font as well) between "arabicdigits" and "digits"
9074
+ % Persian digits: Mapping=farsidigits
9075
+ % Arabic-Indic digits: Mapping=arabicdigits
9076
+ % Western digits: omit Mapping entirely
9012
9077
  \\setdefaultlanguage[calendar=gregorian]{arabic} % from polyglossia
9013
- \\setmainfont[Script=Arabic , Mapping=${digitsMapping}]{Amiri}
9078
+ \\setmainfont${fontOptions(digitsMapping)}{Amiri}
9014
9079
  ${customFonts}
9015
- \\newfontfamily\\boldarabic[Script=Arabic,Mapping=${digitsMapping}]{Amiri Bold}
9016
- \\newfontfamily\\italicarabic[Script=Arabic,Mapping=${digitsMapping}]{Amiri Italic}
9080
+ \\newfontfamily\\boldarabic${fontOptions(digitsMapping)}{Amiri Bold}
9081
+ \\newfontfamily\\italicarabic${fontOptions(digitsMapping)}{Amiri Italic}
9017
9082
 
9018
9083
  % for polyglossia url I dont know, sugggested by cursor
9019
- \\newfontfamily\\arabicfonttt[Script=Arabic,Mapping=${digitsMapping}]{Amiri}
9020
- \\newfontfamily\\arabicfontsf[Script=Arabic,Mapping=${digitsMapping}]{Amiri}
9084
+ \\newfontfamily\\arabicfonttt${fontOptions(digitsMapping)}{Amiri}
9085
+ \\newfontfamily\\arabicfontsf${fontOptions(digitsMapping)}{Amiri}
9021
9086
 
9022
9087
 
9023
9088
  % Explicitly set math font to XITS Math
9024
- % Remove "Script=Arabic" to cancel reflected symbols and other RTL symbols
9025
- \\setmathfont[Script=Arabic , Mapping=${digitsMapping}]{XITS Math} % Ensure XITS Math is correctly installed and available
9089
+ \\setmathfont${mathFontOptions}{XITS Math} % Ensure XITS Math is correctly installed and available
9026
9090
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9027
9091
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9028
9092
  `;
@@ -9184,8 +9248,20 @@ function getArabicXeLatexPreamble(digitsMappingOrOptions = "arabicdigits") {
9184
9248
  }
9185
9249
 
9186
9250
  // src/document2/exportLatex.ts
9251
+ function digitsMappingFromDigitForm(digitForm) {
9252
+ if (digitForm === "western") {
9253
+ return "digits";
9254
+ }
9255
+ if (digitForm === "persianIndic") {
9256
+ return "farsidigits";
9257
+ }
9258
+ return "arabicdigits";
9259
+ }
9187
9260
  function mathBodyLatex(token) {
9188
- if (!token.math || token.sourceOwner === "raw" || token.sourceOwner === "editor") {
9261
+ if (token.sourceOwner === "editor") {
9262
+ return stripDisplayMathDelimiters(mirrorBuTeXOperatorsInTex(token.source, { target: "compile" }));
9263
+ }
9264
+ if (!token.math || token.sourceOwner === "raw") {
9189
9265
  return stripDisplayMathDelimiters(token.source);
9190
9266
  }
9191
9267
  const rendered = renderMathNodeLatex(token.math);
@@ -9221,7 +9297,10 @@ ${body}
9221
9297
  \\label{${token.label.trim()}}
9222
9298
  \\end{equation}`;
9223
9299
  }
9224
- if (!token.math || token.sourceOwner === "raw" || token.sourceOwner === "editor") {
9300
+ if (token.sourceOwner === "editor") {
9301
+ return mirrorBuTeXOperatorsInTex(token.source, { target: "compile" });
9302
+ }
9303
+ if (!token.math || token.sourceOwner === "raw") {
9225
9304
  return token.source;
9226
9305
  }
9227
9306
  return renderMathNodeLatex(token.math);
@@ -9339,7 +9418,7 @@ function articleMaketitlePreamble(meta, twocolumn = false) {
9339
9418
  if (meta.authors.trim().length > 0) {
9340
9419
  parts.push(`\\author{${authorLatex(meta.authors)}}`);
9341
9420
  }
9342
- parts.push(`\\date{${formatHijriDate(meta.date, { locale: "ar", digitForm: "arabicIndic" })}}`);
9421
+ parts.push(`\\date{${formatHijriDate(meta.date, { locale: "ar", digitForm: "western" })}}`);
9343
9422
  return parts.join("\n");
9344
9423
  }
9345
9424
  function articleFrontMatterLatex(meta) {
@@ -9361,7 +9440,7 @@ function document2Latex(document2, options = {}) {
9361
9440
  const twocolumn = options.twocolumn === true;
9362
9441
  const front = articleFrontMatterLatex(meta);
9363
9442
  const bodyBlocks = document2.blocks.map((block) => blockLatex(block, document2.references));
9364
- const closing = butexDiwaniDisplayLatex(BUTEX_CLOSING_HAMDALA);
9443
+ const closing = butexMaghribiDisplayLatex(BUTEX_CLOSING_HAMDALA);
9365
9444
  const body = [...front, ...bodyBlocks, closing].filter((part) => part.length > 0).join("\n\n");
9366
9445
  const wrapDocument = options.wrapDocument !== false;
9367
9446
  if (!wrapDocument) {
@@ -9371,7 +9450,7 @@ function document2Latex(document2, options = {}) {
9371
9450
  ${body}` : body;
9372
9451
  }
9373
9452
  const preamble = getArabicXeLatexPreamble({
9374
- digitsMapping: options.digitsMapping ?? "arabicdigits",
9453
+ digitsMapping: options.digitsMapping ?? digitsMappingFromDigitForm(options.digitForm),
9375
9454
  twocolumn
9376
9455
  }) + "\n" + articleMaketitlePreamble(meta, twocolumn);
9377
9456
  return `${preamble}
@@ -9627,8 +9706,8 @@ function remapSelectionAfterRangeMove(selection, direction) {
9627
9706
  }
9628
9707
 
9629
9708
  // src/document2/previewModel.ts
9630
- function mathTex(token, equationSide) {
9631
- return mathTokenSourceForSide(token, equationSide);
9709
+ function mathTex(token, equationSide, digitForm) {
9710
+ return mathTokenSourceForSide(token, equationSide, digitForm);
9632
9711
  }
9633
9712
  function previewInlines(field, islands, output, equationSide, document2, previewOptions) {
9634
9713
  return field.tokens.map((token) => {
@@ -9660,7 +9739,7 @@ function previewInlines(field, islands, output, equationSide, document2, preview
9660
9739
  }
9661
9740
  const island = {
9662
9741
  id: token.id,
9663
- tex: mathTex(token, equationSide),
9742
+ tex: mathTex(token, equationSide, previewOptions.digitForm),
9664
9743
  display: token.display,
9665
9744
  output,
9666
9745
  editable: token.editable
@@ -9795,7 +9874,7 @@ function document2Preview(document2, output = "svg", equationSide = "arabic", pr
9795
9874
  blocks: [
9796
9875
  ...articleChromePreview(document2, options.uiLocale ?? "ar", options),
9797
9876
  ...body,
9798
- { kind: "closing", id: "article-closing", text: BUTEX_CLOSING_HAMDALA, tex: butexDiwaniDisplayTex(BUTEX_CLOSING_HAMDALA) }
9877
+ { kind: "closing", id: "article-closing", text: BUTEX_CLOSING_HAMDALA, tex: butexMaghribiDisplayTex(BUTEX_CLOSING_HAMDALA) }
9799
9878
  ],
9800
9879
  mathIslands
9801
9880
  };
@@ -10303,6 +10382,32 @@ function focusArticleMetaPanel(panel) {
10303
10382
  // src/react-document2/ButexDocumentEditor2.tsx
10304
10383
  import { useCallback as useCallback2, useEffect as useEffect9, useMemo as useMemo2, useRef as useRef8, useState as useState12 } from "react";
10305
10384
 
10385
+ // src/debugJson.ts
10386
+ function lineColumnForPosition(text, position) {
10387
+ const before = text.slice(0, Math.max(0, position));
10388
+ const lines = before.split("\n");
10389
+ return {
10390
+ line: lines.length,
10391
+ column: (lines[lines.length - 1]?.length ?? 0) + 1
10392
+ };
10393
+ }
10394
+ function parseJsonDebugInput(text) {
10395
+ try {
10396
+ return { ok: true, value: JSON.parse(text) };
10397
+ } catch (error) {
10398
+ const message = error instanceof Error ? error.message : String(error);
10399
+ const positionMatch = message.match(/position\s+(\d+)/i);
10400
+ if (positionMatch) {
10401
+ const position = Number(positionMatch[1]);
10402
+ if (Number.isFinite(position)) {
10403
+ const location = lineColumnForPosition(text, position);
10404
+ return { ok: false, error: `Invalid JSON at line ${String(location.line)}, column ${String(location.column)}: ${message}` };
10405
+ }
10406
+ }
10407
+ return { ok: false, error: `Invalid JSON: ${message}` };
10408
+ }
10409
+ }
10410
+
10306
10411
  // src/react-document2/BlockEditor.tsx
10307
10412
  import { useState as useState3 } from "react";
10308
10413
 
@@ -10842,6 +10947,7 @@ function MathChip({
10842
10947
  token,
10843
10948
  output = "svg",
10844
10949
  documentDirection = "rtl",
10950
+ digitForm,
10845
10951
  equationSide = "arabic",
10846
10952
  editable = true,
10847
10953
  uiLocale = "ar",
@@ -10853,7 +10959,7 @@ function MathChip({
10853
10959
  onTextInputFromFocus
10854
10960
  }) {
10855
10961
  const messages = document2Messages(uiLocale);
10856
- const tex = mathTokenSourceForSide(token, equationSide);
10962
+ const tex = mathTokenSourceForSide(token, equationSide, digitForm);
10857
10963
  const forwardArrowKey = documentDirection === "rtl" ? "ArrowLeft" : "ArrowRight";
10858
10964
  const backwardArrowKey = documentDirection === "rtl" ? "ArrowRight" : "ArrowLeft";
10859
10965
  const island = /* @__PURE__ */ jsx4(MathIsland, { id: token.id, tex, display: token.display, output });
@@ -11263,6 +11369,7 @@ function InlineField({
11263
11369
  token,
11264
11370
  output: mathOutput,
11265
11371
  equationSide,
11372
+ digitForm,
11266
11373
  editable: editableEquations,
11267
11374
  uiLocale,
11268
11375
  buttonRef: (element) => {
@@ -12814,6 +12921,11 @@ var WIDGET_CHROME_CSS = `
12814
12921
  font-family: ${BUTEX_DIWANI_OUTLINE_FONT_STACK};
12815
12922
  }
12816
12923
 
12924
+ .butex-widget .font-mode-btn--maghribi,
12925
+ .butex-widget .character-font-option--maghribi {
12926
+ font-family: ${BUTEX_MAGHRIBI_FONT_STACK};
12927
+ }
12928
+
12817
12929
  .butex-widget .character-font-options {
12818
12930
  position: absolute;
12819
12931
  z-index: 10;
@@ -13348,6 +13460,36 @@ var WIDGET_CHROME_CSS = `
13348
13460
  background: var(--butex-dev-inset-bg);
13349
13461
  color: var(--butex-dev-inset-fg);
13350
13462
  }
13463
+
13464
+ .butex-widget .debug-json-import {
13465
+ display: grid;
13466
+ gap: 8px;
13467
+ margin-bottom: 10px;
13468
+ }
13469
+
13470
+ .butex-widget .debug-json-import textarea {
13471
+ min-height: 150px;
13472
+ resize: vertical;
13473
+ border: 1px solid var(--butex-dev-inset-border);
13474
+ border-radius: 8px;
13475
+ padding: 8px 10px;
13476
+ direction: ltr;
13477
+ text-align: left;
13478
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
13479
+ font-size: 11px;
13480
+ background: var(--butex-dev-inset-bg);
13481
+ color: var(--butex-dev-inset-fg);
13482
+ }
13483
+
13484
+ .butex-widget .debug-json-error {
13485
+ margin: 0;
13486
+ border: 1px solid rgba(220, 38, 38, 0.45);
13487
+ background: rgba(254, 226, 226, 0.9);
13488
+ color: #991b1b;
13489
+ border-radius: 8px;
13490
+ padding: 8px 10px;
13491
+ white-space: pre-wrap;
13492
+ }
13351
13493
  `.trim();
13352
13494
  var CHROME_STYLE_ID = "butex-widget-chrome-css";
13353
13495
  function injectWidgetChromeCss(doc) {
@@ -13476,6 +13618,7 @@ ${latex || messages.empty}`;
13476
13618
  var ButexEditor = forwardRef(
13477
13619
  function ButexEditor2({ className, debug = false, defaultSide, uiLocale = "ar", initialSession, onSessionChange }, ref) {
13478
13620
  const messages = equationEditorMessages(uiLocale);
13621
+ const debugEnabled = debug || typeof window !== "undefined" && new URLSearchParams(window.location.search).get("debug") === "1";
13479
13622
  const wrapperRef = useRef6(null);
13480
13623
  const surfaceRef = useRef6(null);
13481
13624
  const inputRef = useRef6(null);
@@ -13493,7 +13636,7 @@ var ButexEditor = forwardRef(
13493
13636
  const digitFormBtnRef = useRef6(null);
13494
13637
  const runtimeRef = useRef6(null);
13495
13638
  const debugRef = useRef6(debug);
13496
- debugRef.current = debug;
13639
+ debugRef.current = debugEnabled;
13497
13640
  const uiLocaleRef = useRef6(uiLocale);
13498
13641
  uiLocaleRef.current = uiLocale;
13499
13642
  const onSessionChangeRef = useRef6(onSessionChange);
@@ -13501,6 +13644,9 @@ var ButexEditor = forwardRef(
13501
13644
  const debugBodyHiddenRef = useRef6(false);
13502
13645
  const [debugBodyHidden, setDebugBodyHidden] = useState7(false);
13503
13646
  debugBodyHiddenRef.current = debugBodyHidden;
13647
+ const [debugImportOpen, setDebugImportOpen] = useState7(false);
13648
+ const [debugImportText, setDebugImportText] = useState7("");
13649
+ const [debugImportError, setDebugImportError] = useState7("");
13504
13650
  const [digitMenuOpen, setDigitMenuOpen] = useState7(false);
13505
13651
  const [characterFontMenuOpen, setCharacterFontMenuOpen] = useState7(false);
13506
13652
  const [delimiterMenuOpen, setDelimiterMenuOpen] = useState7(false);
@@ -13581,6 +13727,54 @@ ${arabic || currentMessages.empty}`;
13581
13727
  }, []);
13582
13728
  const updatePreviewRef = useRef6(updatePreview);
13583
13729
  updatePreviewRef.current = updatePreview;
13730
+ async function copyDebugText(text) {
13731
+ try {
13732
+ await navigator.clipboard.writeText(text);
13733
+ } catch {
13734
+ }
13735
+ }
13736
+ function currentMathObjectJsonText() {
13737
+ const session = runtimeRef.current?.getSession();
13738
+ if (!session) {
13739
+ return "";
13740
+ }
13741
+ const math = mathNodeFromEditorSession(session);
13742
+ if (!math.ok) {
13743
+ return "";
13744
+ }
13745
+ return JSON.stringify(toMathObjectJson(math.math), null, 2);
13746
+ }
13747
+ function openDebugMathObjectImport() {
13748
+ setDebugImportText(currentMathObjectJsonText());
13749
+ setDebugImportError("");
13750
+ setDebugImportOpen(true);
13751
+ }
13752
+ function applyDebugMathObjectImport() {
13753
+ const parsed = parseJsonDebugInput(debugImportText);
13754
+ if (!parsed.ok) {
13755
+ setDebugImportError(parsed.error);
13756
+ return;
13757
+ }
13758
+ try {
13759
+ const math = fromMathObjectJson(parsed.value, activeEditorSide);
13760
+ const result = mathObjectToEditorSession(math);
13761
+ if (!result.editable) {
13762
+ setDebugImportError(result.reason);
13763
+ return;
13764
+ }
13765
+ const next = { ...result.session, activeSide: activeEditorSide };
13766
+ runtimeRef.current?.setSession(next);
13767
+ setSelectedDigitForm(next.currentDigitForm ?? "western");
13768
+ setSelectedCharacterFont(next.currentCharacterFont ?? "default");
13769
+ setActiveEditorSide(next.activeSide);
13770
+ onSessionChangeRef.current?.(next);
13771
+ setDebugImportError("");
13772
+ setDebugImportOpen(false);
13773
+ void updatePreviewRef.current(next);
13774
+ } catch (importError) {
13775
+ setDebugImportError(importError instanceof Error ? importError.message : String(importError));
13776
+ }
13777
+ }
13584
13778
  useEffect6(() => {
13585
13779
  injectWidgetChromeCss();
13586
13780
  injectBuTeXEditorStyles(typeof document !== "undefined" ? document : void 0);
@@ -14741,7 +14935,7 @@ ${arabic || currentMessages.empty}`;
14741
14935
  /* @__PURE__ */ jsx12("div", { ref: renderErrorRef, className: "error", hidden: true })
14742
14936
  ] }),
14743
14937
  /* @__PURE__ */ jsx12("section", { className: "panel panel-preview", "aria-label": messages.renderPreview, children: /* @__PURE__ */ jsx12("div", { ref: mathOutputRef, className: "preview-box" }) }),
14744
- debug ? /* @__PURE__ */ jsxs10("section", { className: "panel", children: [
14938
+ debugEnabled ? /* @__PURE__ */ jsxs10("section", { className: "panel", children: [
14745
14939
  /* @__PURE__ */ jsxs10("div", { className: "dev-strip", children: [
14746
14940
  /* @__PURE__ */ jsx12("span", { className: "dev-badge", children: messages.development }),
14747
14941
  /* @__PURE__ */ jsx12("div", { ref: latexLinesRef, className: "ascii" }),
@@ -14749,6 +14943,8 @@ ${arabic || currentMessages.empty}`;
14749
14943
  ] }),
14750
14944
  /* @__PURE__ */ jsxs10("div", { style: { marginTop: 12 }, children: [
14751
14945
  /* @__PURE__ */ jsxs10("div", { className: "debug-head", children: [
14946
+ /* @__PURE__ */ jsx12("button", { type: "button", onClick: () => void copyDebugText(currentMathObjectJsonText()), children: "Copy MathObject JSON" }),
14947
+ /* @__PURE__ */ jsx12("button", { type: "button", "aria-expanded": debugImportOpen, onClick: openDebugMathObjectImport, children: "Import MathObject JSON" }),
14752
14948
  /* @__PURE__ */ jsx12(
14753
14949
  "button",
14754
14950
  {
@@ -14784,6 +14980,35 @@ ${arabic || currentMessages.empty}`;
14784
14980
  }
14785
14981
  )
14786
14982
  ] }),
14983
+ debugImportOpen ? /* @__PURE__ */ jsxs10("div", { className: "debug-json-import", children: [
14984
+ /* @__PURE__ */ jsx12(
14985
+ "textarea",
14986
+ {
14987
+ value: debugImportText,
14988
+ "aria-label": "Import MathObject JSON",
14989
+ spellCheck: false,
14990
+ onChange: (event) => {
14991
+ setDebugImportText(event.currentTarget.value);
14992
+ setDebugImportError("");
14993
+ }
14994
+ }
14995
+ ),
14996
+ /* @__PURE__ */ jsxs10("div", { className: "debug-head", children: [
14997
+ /* @__PURE__ */ jsx12("button", { type: "button", onClick: applyDebugMathObjectImport, children: "Apply" }),
14998
+ /* @__PURE__ */ jsx12(
14999
+ "button",
15000
+ {
15001
+ type: "button",
15002
+ onClick: () => {
15003
+ setDebugImportOpen(false);
15004
+ setDebugImportError("");
15005
+ },
15006
+ children: "Cancel"
15007
+ }
15008
+ )
15009
+ ] }),
15010
+ debugImportError ? /* @__PURE__ */ jsx12("p", { className: "debug-json-error", children: debugImportError }) : null
15011
+ ] }) : null,
14787
15012
  /* @__PURE__ */ jsx12("div", { ref: debugLogRef, className: "debug-log" })
14788
15013
  ] })
14789
15014
  ] }) : null
@@ -14809,6 +15034,7 @@ function keyErrorMessage2(error, messages) {
14809
15034
  return null;
14810
15035
  }
14811
15036
  function EquationDrawer({
15037
+ debug = false,
14812
15038
  session,
14813
15039
  reason,
14814
15040
  mathMode,
@@ -14926,7 +15152,7 @@ function EquationDrawer({
14926
15152
  /* @__PURE__ */ jsx13(
14927
15153
  ButexEditor,
14928
15154
  {
14929
- debug: false,
15155
+ debug,
14930
15156
  defaultSide: equationSide,
14931
15157
  uiLocale,
14932
15158
  initialSession: session,
@@ -16508,6 +16734,42 @@ var DOCUMENT2_WIDGET_CSS = `
16508
16734
  white-space: pre-wrap;
16509
16735
  }
16510
16736
 
16737
+ .butex-document2-widget__dev-actions {
16738
+ display: flex;
16739
+ flex-wrap: wrap;
16740
+ gap: 8px;
16741
+ margin: 0 0 10px;
16742
+ }
16743
+
16744
+ .butex-document2-widget__dev-import {
16745
+ display: grid;
16746
+ gap: 8px;
16747
+ margin-bottom: 12px;
16748
+ }
16749
+
16750
+ .butex-document2-widget__dev-import textarea {
16751
+ background: var(--butex-document2-dev-code-bg);
16752
+ border: 1px solid var(--butex-document2-dev-border);
16753
+ border-radius: 8px;
16754
+ color: var(--butex-document2-dev-code-fg);
16755
+ direction: ltr;
16756
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
16757
+ min-height: 180px;
16758
+ padding: 10px;
16759
+ resize: vertical;
16760
+ text-align: left;
16761
+ }
16762
+
16763
+ .butex-document2-widget__dev-error {
16764
+ background: rgba(254, 226, 226, 0.9);
16765
+ border: 1px solid rgba(220, 38, 38, 0.45);
16766
+ border-radius: 8px;
16767
+ color: #991b1b;
16768
+ margin: 0;
16769
+ padding: 8px 10px;
16770
+ white-space: pre-wrap;
16771
+ }
16772
+
16511
16773
  .butex-document2-widget__dev-diagnostic {
16512
16774
  background: rgba(251, 191, 36, 0.18);
16513
16775
  border: 1px solid rgba(217, 119, 6, 0.4);
@@ -17371,11 +17633,17 @@ function ButexDocumentEditor2({
17371
17633
  const [labelsOpen, setLabelsOpen] = useState12(false);
17372
17634
  const [refPicker, setRefPicker] = useState12(null);
17373
17635
  const [digitFormState, setDigitFormState] = useState12(null);
17636
+ const [debugImportOpen, setDebugImportOpen] = useState12(false);
17637
+ const [debugImportText, setDebugImportText] = useState12("");
17638
+ const [debugImportError, setDebugImportError] = useState12("");
17374
17639
  const [editorFocus, setEditorFocus] = useState12(createEmptyDocument2EditorFocus());
17375
17640
  const [collapsedBlockIds, setCollapsedBlockIds] = useState12(() => /* @__PURE__ */ new Set());
17376
17641
  const [blockSelectionState, setBlockSelectionState] = useState12(emptyBlockSelection);
17377
17642
  const [historyTick, setHistoryTick] = useState12(0);
17378
17643
  const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
17644
+ function equationSessionWithDocumentDigits(session) {
17645
+ return setCurrentDigitForm(session, digitForm);
17646
+ }
17379
17647
  const historyRef = useRef8(createDocument2History());
17380
17648
  const documentRef = useRef8(documentNode);
17381
17649
  const textSnapshotArmedRef = useRef8(false);
@@ -17384,7 +17652,7 @@ function ButexDocumentEditor2({
17384
17652
  const articleMetaPanelRef = useRef8(null);
17385
17653
  const pendingFocusRef = useRef8(null);
17386
17654
  documentRef.current = documentNode;
17387
- const latex = document2Latex(documentNode);
17655
+ const latex = document2Latex(documentNode, { digitForm });
17388
17656
  const documentJson = useMemo2(() => toDocumentJson2(documentNode), [documentNode]);
17389
17657
  const documentLabels = useMemo2(() => collectDocument2Labels(documentNode), [documentNode]);
17390
17658
  const preview = useMemo2(
@@ -17592,6 +17860,46 @@ function ButexDocumentEditor2({
17592
17860
  function openAllBlocks() {
17593
17861
  setCollapsedBlockIds(/* @__PURE__ */ new Set());
17594
17862
  }
17863
+ async function copyDebugText(text) {
17864
+ try {
17865
+ await navigator.clipboard.writeText(text);
17866
+ } catch {
17867
+ }
17868
+ }
17869
+ function openDebugJsonImport() {
17870
+ setDebugImportText(JSON.stringify(documentJson, null, 2));
17871
+ setDebugImportError("");
17872
+ setDebugImportOpen(true);
17873
+ }
17874
+ function applyDebugJsonImport() {
17875
+ const parsed = parseJsonDebugInput(debugImportText);
17876
+ if (!parsed.ok) {
17877
+ setDebugImportError(parsed.error);
17878
+ return;
17879
+ }
17880
+ try {
17881
+ const imported = fromDocumentJson2(parsed.value);
17882
+ textSnapshotArmedRef.current = false;
17883
+ if (textDebounceRef.current !== null) {
17884
+ window.clearTimeout(textDebounceRef.current);
17885
+ textDebounceRef.current = null;
17886
+ }
17887
+ setDocumentNode(imported);
17888
+ setError(null);
17889
+ setSelectedMath(null);
17890
+ setCitePicker(null);
17891
+ setRefPicker(null);
17892
+ clearBlockSelection();
17893
+ setCollapsedBlockIds(/* @__PURE__ */ new Set());
17894
+ setEditorFocus(createEmptyDocument2EditorFocus());
17895
+ historyRef.current = createDocument2History();
17896
+ bumpHistoryUi();
17897
+ setDebugImportError("");
17898
+ setDebugImportOpen(false);
17899
+ } catch (importError) {
17900
+ setDebugImportError(importError instanceof Error ? importError.message : String(importError));
17901
+ }
17902
+ }
17595
17903
  useEffect9(() => {
17596
17904
  const root = widgetRef.current;
17597
17905
  if (!root) {
@@ -17647,7 +17955,7 @@ function ButexDocumentEditor2({
17647
17955
  textTokenId: target?.textTokenId ?? null,
17648
17956
  insertAt: target?.caretOffset ?? 0,
17649
17957
  mathMode: mode,
17650
- session: createEmptyEquationSession(equationSide),
17958
+ session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
17651
17959
  reason: null,
17652
17960
  labelEnabled: false,
17653
17961
  label: ""
@@ -17667,7 +17975,7 @@ function ButexDocumentEditor2({
17667
17975
  insertAt: 0,
17668
17976
  textTokenId: null,
17669
17977
  mathMode: mode,
17670
- session: createEmptyEquationSession(equationSide),
17978
+ session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
17671
17979
  reason: result.reason,
17672
17980
  labelEnabled: Boolean(token.labelEnabled),
17673
17981
  label: token.label ?? ""
@@ -17680,7 +17988,7 @@ function ButexDocumentEditor2({
17680
17988
  insertAt: 0,
17681
17989
  textTokenId: null,
17682
17990
  mathMode: mode,
17683
- session: result.session,
17991
+ session: equationSessionWithDocumentDigits(result.session),
17684
17992
  reason: null,
17685
17993
  labelEnabled: Boolean(token.labelEnabled),
17686
17994
  label: token.label ?? ""
@@ -18105,14 +18413,51 @@ function ButexDocumentEditor2({
18105
18413
  /* @__PURE__ */ jsx17("strong", { children: messages.importWarnings }),
18106
18414
  documentNode.diagnostics.map((diagnostic) => /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__dev-diagnostic", children: formatDocument2Diagnostic(diagnostic, messages) }, `${diagnostic.path}-${diagnostic.message}`))
18107
18415
  ] }) : null,
18416
+ /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev-actions", children: [
18417
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => void copyDebugText(JSON.stringify(documentJson, null, 2)), children: "Copy JSON" }),
18418
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => void copyDebugText(latex), children: "Copy TeX" }),
18419
+ /* @__PURE__ */ jsx17("button", { type: "button", "aria-expanded": debugImportOpen, onClick: openDebugJsonImport, children: "Import JSON" })
18420
+ ] }),
18421
+ debugImportOpen ? /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev-import", children: [
18422
+ /* @__PURE__ */ jsx17(
18423
+ "textarea",
18424
+ {
18425
+ value: debugImportText,
18426
+ "aria-label": "Import Document2 JSON",
18427
+ spellCheck: false,
18428
+ onChange: (event) => {
18429
+ setDebugImportText(event.currentTarget.value);
18430
+ setDebugImportError("");
18431
+ }
18432
+ }
18433
+ ),
18434
+ /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev-actions", children: [
18435
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: applyDebugJsonImport, children: "Apply" }),
18436
+ /* @__PURE__ */ jsx17(
18437
+ "button",
18438
+ {
18439
+ type: "button",
18440
+ onClick: () => {
18441
+ setDebugImportOpen(false);
18442
+ setDebugImportError("");
18443
+ },
18444
+ children: "Cancel"
18445
+ }
18446
+ )
18447
+ ] }),
18448
+ debugImportError ? /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__dev-error", children: debugImportError }) : null
18449
+ ] }) : null,
18108
18450
  /* @__PURE__ */ jsx17("strong", { children: "LaTeX" }),
18109
18451
  /* @__PURE__ */ jsx17("pre", { children: latex }),
18452
+ /* @__PURE__ */ jsx17("strong", { children: "JSON" }),
18453
+ /* @__PURE__ */ jsx17("pre", { children: JSON.stringify(documentJson, null, 2) }),
18110
18454
  /* @__PURE__ */ jsx17("strong", { children: "AST" }),
18111
18455
  /* @__PURE__ */ jsx17("pre", { children: JSON.stringify(documentNode, null, 2) })
18112
18456
  ] }) : null,
18113
18457
  !previewOnly && selectedMath ? /* @__PURE__ */ jsx17(
18114
18458
  EquationDrawer,
18115
18459
  {
18460
+ debug: debugEnabled,
18116
18461
  session: selectedMath.session,
18117
18462
  reason: selectedMath.reason,
18118
18463
  mathMode: selectedMath.mathMode,