@drghaliasri/butex 5.5.5 → 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.
@@ -100,7 +100,9 @@ function butexBasmalaDisplayTex() {
100
100
  }
101
101
  function butexBasmalaDisplayLatex() {
102
102
  return `\\[
103
- ${butexBasmalaDisplayTex()}
103
+ \\begin{gathered}
104
+ ${BASMALA_LINES.map((line) => butexMaghribiDisplayTex(line)).join(" \\\\\n")}
105
+ \\end{gathered}
104
106
  \\]`;
105
107
  }
106
108
  function butexInColumnMaketitleHook() {
@@ -2102,6 +2104,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2102
2104
  category: "operators1",
2103
2105
  Tex: "\\neq",
2104
2106
  mirror: true,
2107
+ compileMirror: true,
2105
2108
  Label: "\u2260",
2106
2109
  title: "\u0644\u0627 \u064A\u0633\u0627\u0648\u064A",
2107
2110
  svg_path: null
@@ -2141,6 +2144,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2141
2144
  Tex: "\\leq",
2142
2145
  mirror: true,
2143
2146
  displayMirror: false,
2147
+ compileMirror: true,
2144
2148
  Label: "\u2264",
2145
2149
  title: "\u0623\u0635\u063A\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
2146
2150
  svg_path: null
@@ -2151,6 +2155,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2151
2155
  Tex: "\\geq",
2152
2156
  mirror: true,
2153
2157
  displayMirror: false,
2158
+ compileMirror: true,
2154
2159
  Label: "\u2265",
2155
2160
  title: "\u0623\u0643\u0628\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
2156
2161
  svg_path: null
@@ -2161,6 +2166,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2161
2166
  Tex: "\\coloneqq",
2162
2167
  mirror: true,
2163
2168
  displayMirror: false,
2169
+ compileMirror: true,
2164
2170
  Label: "\u2254",
2165
2171
  title: "\u064A\u0639\u0631\u0641 \u0628\u0623\u0646\u0647 \u064A\u0633\u0627\u0648\u064A",
2166
2172
  svg_path: null
@@ -2171,6 +2177,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2171
2177
  Tex: "\\eqqcolon",
2172
2178
  mirror: true,
2173
2179
  displayMirror: false,
2180
+ compileMirror: true,
2174
2181
  Label: "\u2255",
2175
2182
  title: "\u064A\u0633\u0627\u0648\u064A \u0628\u0627\u0644\u062A\u0639\u0631\u064A\u0641",
2176
2183
  svg_path: null
@@ -2182,6 +2189,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2182
2189
  Tex: "\\propto",
2183
2190
  mirror: true,
2184
2191
  displayMirror: false,
2192
+ compileMirror: true,
2185
2193
  Label: "\u221D",
2186
2194
  title: "\u064A\u062A\u0646\u0627\u0633\u0628 \u0645\u0639",
2187
2195
  svg_path: null
@@ -2192,6 +2200,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2192
2200
  Tex: "\\in",
2193
2201
  mirror: true,
2194
2202
  displayMirror: false,
2203
+ compileMirror: true,
2195
2204
  Label: "\u2208",
2196
2205
  title: "\u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
2197
2206
  svg_path: null
@@ -2212,6 +2221,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2212
2221
  Tex: "\\subset",
2213
2222
  mirror: true,
2214
2223
  displayMirror: false,
2224
+ compileMirror: true,
2215
2225
  Label: "\u2282",
2216
2226
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0645\u0646",
2217
2227
  svg_path: null
@@ -2222,6 +2232,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2222
2232
  Tex: "\\supset",
2223
2233
  mirror: true,
2224
2234
  displayMirror: false,
2235
+ compileMirror: true,
2225
2236
  Label: "\u2283",
2226
2237
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0644\u0640",
2227
2238
  svg_path: null
@@ -2232,6 +2243,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2232
2243
  Tex: "\\subseteq",
2233
2244
  mirror: true,
2234
2245
  displayMirror: false,
2246
+ compileMirror: true,
2235
2247
  Label: "\u2286",
2236
2248
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
2237
2249
  svg_path: null
@@ -2242,6 +2254,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2242
2254
  Tex: "\\supseteq",
2243
2255
  mirror: true,
2244
2256
  displayMirror: false,
2257
+ compileMirror: true,
2245
2258
  Label: "\u2287",
2246
2259
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
2247
2260
  svg_path: null
@@ -2282,6 +2295,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2282
2295
  Tex: "\\nsubseteq",
2283
2296
  mirror: true,
2284
2297
  displayMirror: false,
2298
+ compileMirror: true,
2285
2299
  Label: "\u2288",
2286
2300
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
2287
2301
  svg_path: null
@@ -2292,6 +2306,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2292
2306
  Tex: "\\nsupseteq",
2293
2307
  mirror: true,
2294
2308
  displayMirror: false,
2309
+ compileMirror: true,
2295
2310
  Label: "\u2289",
2296
2311
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
2297
2312
  svg_path: null
@@ -2339,6 +2354,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2339
2354
  Tex: "\\ddots",
2340
2355
  mirror: true,
2341
2356
  displayMirror: false,
2357
+ compileMirror: true,
2342
2358
  Label: "\u22F1",
2343
2359
  title: "\u0646\u0642\u0627\u0637 \u0642\u0637\u0631\u064A\u0629",
2344
2360
  svg_path: null
@@ -2358,6 +2374,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2358
2374
  category: "operators3",
2359
2375
  Tex: "\\implies",
2360
2376
  mirror: true,
2377
+ compileMirror: true,
2361
2378
  Label: "\u21D2",
2362
2379
  title: "\u064A\u0633\u062A\u0644\u0632\u0645",
2363
2380
  svg_path: null
@@ -2367,6 +2384,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2367
2384
  category: "operators3",
2368
2385
  Tex: "\\impliedby",
2369
2386
  mirror: true,
2387
+ compileMirror: true,
2370
2388
  Label: "\u21D0",
2371
2389
  title: "\u0645\u0633\u062A\u0644\u0632\u0645 \u0645\u0646",
2372
2390
  svg_path: null
@@ -2385,6 +2403,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2385
2403
  category: "operators3",
2386
2404
  Tex: "\\Longrightarrow",
2387
2405
  mirror: true,
2406
+ compileMirror: true,
2388
2407
  Label: "\u27F9",
2389
2408
  title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0637\u0648\u064A\u0644 \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2390
2409
  svg_path: null
@@ -2394,6 +2413,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2394
2413
  category: "operators3",
2395
2414
  Tex: "\\Longleftarrow",
2396
2415
  mirror: true,
2416
+ compileMirror: true,
2397
2417
  Label: "\u27F8",
2398
2418
  title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0637\u0648\u064A\u0644 \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2399
2419
  svg_path: null
@@ -2403,6 +2423,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2403
2423
  category: "operators3",
2404
2424
  Tex: "\\to",
2405
2425
  mirror: true,
2426
+ compileMirror: true,
2406
2427
  Label: "\u2192",
2407
2428
  title: "\u064A\u0624\u0648\u0644 \u0625\u0644\u0649",
2408
2429
  svg_path: null
@@ -2412,6 +2433,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2412
2433
  category: "operators3",
2413
2434
  Tex: "\\rightleftharpoons",
2414
2435
  mirror: true,
2436
+ compileMirror: true,
2415
2437
  Label: "\u21CC",
2416
2438
  title: "\u0627\u062A\u0632\u0627\u0646",
2417
2439
  svg_path: null
@@ -2421,6 +2443,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2421
2443
  category: "operators3",
2422
2444
  Tex: "\\leftarrow",
2423
2445
  mirror: true,
2446
+ compileMirror: true,
2424
2447
  Label: "\u2190",
2425
2448
  title: "\u0633\u0647\u0645 \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2426
2449
  svg_path: null
@@ -2430,6 +2453,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2430
2453
  category: "operators3",
2431
2454
  Tex: "\\rightarrow",
2432
2455
  mirror: true,
2456
+ compileMirror: true,
2433
2457
  Label: "\u2192",
2434
2458
  title: "\u0633\u0647\u0645 \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2435
2459
  svg_path: null
@@ -2439,6 +2463,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2439
2463
  category: "operators3",
2440
2464
  Tex: "\\Leftarrow",
2441
2465
  mirror: true,
2466
+ compileMirror: true,
2442
2467
  Label: "\u21D0",
2443
2468
  title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2444
2469
  svg_path: null
@@ -2448,6 +2473,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2448
2473
  category: "operators3",
2449
2474
  Tex: "\\Rightarrow",
2450
2475
  mirror: true,
2476
+ compileMirror: true,
2451
2477
  Label: "\u21D2",
2452
2478
  title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2453
2479
  svg_path: null
@@ -2457,6 +2483,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2457
2483
  category: "operators3",
2458
2484
  Tex: "\\leftharpoonup",
2459
2485
  mirror: true,
2486
+ compileMirror: true,
2460
2487
  Label: "\u21BC",
2461
2488
  title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2462
2489
  svg_path: null
@@ -2466,6 +2493,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2466
2493
  category: "operators3",
2467
2494
  Tex: "\\rightharpoonup",
2468
2495
  mirror: true,
2496
+ compileMirror: true,
2469
2497
  Label: "\u21C0",
2470
2498
  title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2471
2499
  svg_path: null
@@ -2475,6 +2503,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2475
2503
  category: "operators3",
2476
2504
  Tex: "\\leftharpoondown",
2477
2505
  mirror: true,
2506
+ compileMirror: true,
2478
2507
  Label: "\u21BD",
2479
2508
  title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0633\u0641\u0644\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
2480
2509
  svg_path: null
@@ -2484,6 +2513,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2484
2513
  category: "operators3",
2485
2514
  Tex: "\\rightharpoondown",
2486
2515
  mirror: true,
2516
+ compileMirror: true,
2487
2517
  Label: "\u21C1",
2488
2518
  title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0633\u0641\u0644\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
2489
2519
  svg_path: null
@@ -2494,6 +2524,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2494
2524
  category: "integrals",
2495
2525
  Tex: "\\int",
2496
2526
  mirror: true,
2527
+ compileMirror: true,
2497
2528
  Label: "\u222B",
2498
2529
  title: "\u062A\u0643\u0627\u0645\u0644",
2499
2530
  svg_path: null
@@ -2504,6 +2535,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2504
2535
  Tex: "\\iint",
2505
2536
  mirror: true,
2506
2537
  displayMirror: false,
2538
+ compileMirror: true,
2507
2539
  Label: "\u222C",
2508
2540
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u0632\u062F\u0648\u062C",
2509
2541
  svg_path: null
@@ -2514,6 +2546,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2514
2546
  Tex: "\\iiint",
2515
2547
  mirror: true,
2516
2548
  displayMirror: false,
2549
+ compileMirror: true,
2517
2550
  Label: "\u222D",
2518
2551
  title: "\u062A\u0643\u0627\u0645\u0644 \u062B\u0644\u0627\u062B\u064A",
2519
2552
  svg_path: null
@@ -2524,6 +2557,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2524
2557
  Tex: "\\iiiint",
2525
2558
  mirror: true,
2526
2559
  displayMirror: false,
2560
+ compileMirror: true,
2527
2561
  Label: "\u2A0C",
2528
2562
  title: "\u062A\u0643\u0627\u0645\u0644 \u0631\u0628\u0627\u0639\u064A",
2529
2563
  svg_path: null
@@ -2534,6 +2568,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2534
2568
  Tex: "\\oint",
2535
2569
  mirror: true,
2536
2570
  displayMirror: false,
2571
+ compileMirror: true,
2537
2572
  Label: "\u222E",
2538
2573
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u063A\u0644\u0642",
2539
2574
  svg_path: null
@@ -2544,6 +2579,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2544
2579
  Tex: "\\oiint",
2545
2580
  mirror: true,
2546
2581
  displayMirror: false,
2582
+ compileMirror: true,
2547
2583
  Label: "\u222F",
2548
2584
  title: "\u062A\u0643\u0627\u0645\u0644 \u0633\u0637\u062D\u064A \u0645\u063A\u0644\u0642",
2549
2585
  svg_path: null
@@ -2554,6 +2590,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2554
2590
  Tex: "\\oiiint",
2555
2591
  mirror: true,
2556
2592
  displayMirror: false,
2593
+ compileMirror: true,
2557
2594
  Label: "\u2230",
2558
2595
  title: "\u062A\u0643\u0627\u0645\u0644 \u062D\u062C\u0645\u064A \u0645\u063A\u0644\u0642",
2559
2596
  svg_path: null
@@ -2563,8 +2600,9 @@ function shouldMirrorOperatorDisplay(command) {
2563
2600
  return command?.displayMirror ?? command?.mirror ?? false;
2564
2601
  }
2565
2602
  var MIRRORED_OPERATOR_TEX = Object.values(ATOMIC_OPERATOR_COMMANDS).filter((command) => command.mirror).map((command) => command.Tex).sort((a, b) => b.length - a.length);
2566
- function matchingMirroredOperator(tex, index) {
2567
- for (const operatorTex of MIRRORED_OPERATOR_TEX) {
2603
+ 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);
2604
+ function matchingMirroredOperatorFrom(tex, index, operatorTexList) {
2605
+ for (const operatorTex of operatorTexList) {
2568
2606
  if (!tex.startsWith(operatorTex, index)) {
2569
2607
  continue;
2570
2608
  }
@@ -2595,19 +2633,26 @@ function findMatchingBrace(tex, openIndex) {
2595
2633
  }
2596
2634
  return -1;
2597
2635
  }
2598
- function mirrorBuTeXOperatorsInTex(tex) {
2636
+ function mirrorBuTeXOperatorsInTex(tex, options = {}) {
2637
+ const mirroredOperatorTex = options.target === "compile" ? COMPILE_MIRRORED_OPERATOR_TEX : MIRRORED_OPERATOR_TEX;
2599
2638
  let result = "";
2600
2639
  let index = 0;
2601
2640
  while (index < tex.length) {
2602
2641
  if (tex.startsWith("\\butexmirror{", index)) {
2603
2642
  const end = findMatchingBrace(tex, index + "\\butexmirror".length);
2604
2643
  if (end !== -1) {
2605
- result += tex.slice(index, end + 1);
2644
+ const bodyStart = index + "\\butexmirror{".length;
2645
+ const body = tex.slice(bodyStart, end);
2646
+ if (options.target === "compile" && MIRRORED_OPERATOR_TEX.includes(body) && !mirroredOperatorTex.includes(body)) {
2647
+ result += body;
2648
+ } else {
2649
+ result += tex.slice(index, end + 1);
2650
+ }
2606
2651
  index = end + 1;
2607
2652
  continue;
2608
2653
  }
2609
2654
  }
2610
- const operatorTex = matchingMirroredOperator(tex, index);
2655
+ const operatorTex = matchingMirroredOperatorFrom(tex, index, mirroredOperatorTex);
2611
2656
  if (operatorTex) {
2612
2657
  result += `\\butexmirror{${operatorTex}}`;
2613
2658
  index += operatorTex.length;
@@ -8269,18 +8314,19 @@ function mathNodeFromSession(session, opening = "$", closing = "$") {
8269
8314
  }
8270
8315
  return { nodeType: "MathObject", mathMode: opening, lines: [], closing };
8271
8316
  }
8272
- function mathTokenSourceForSide(token, side) {
8317
+ function mathTokenSourceForSide(token, side, digitForm) {
8273
8318
  if (!token.math || token.sourceOwner === "raw") {
8274
8319
  return token.source;
8275
8320
  }
8276
- if (token.sourceSide === side) {
8321
+ if (token.sourceSide === side && digitForm === void 0) {
8277
8322
  return token.source;
8278
8323
  }
8279
8324
  const result = mathTokenToEditorSession(token.math, side);
8280
8325
  if (!result.editable) {
8281
8326
  return token.source;
8282
8327
  }
8283
- return mathSourceFromSession(result.session, side, token.opening, token.closing);
8328
+ const session = digitForm === void 0 ? result.session : setCurrentDigitForm(result.session, digitForm);
8329
+ return mathSourceFromSession(session, side, token.opening, token.closing);
8284
8330
  }
8285
8331
 
8286
8332
  // src/document2/commands.ts
@@ -9014,6 +9060,19 @@ function document2KeyError(key, namespace = {}) {
9014
9060
  }
9015
9061
 
9016
9062
  // src/document2/arabicPreamble.ts
9063
+ function fontOptions(digitsMapping, includeScript = true) {
9064
+ const parts = [];
9065
+ if (includeScript) {
9066
+ parts.push("Script=Arabic");
9067
+ }
9068
+ if (digitsMapping !== "digits") {
9069
+ parts.push(`Mapping=${digitsMapping}`);
9070
+ }
9071
+ if (parts.length === 0) {
9072
+ return "";
9073
+ }
9074
+ return `[${parts.join(",")}]`;
9075
+ }
9017
9076
  function arabicXeLatexPreamblePkg(twocolumn = false) {
9018
9077
  const classOptions = twocolumn ? "12pt,a4paper,notitlepage,twocolumn" : "12pt,a4paper,notitlepage";
9019
9078
  return `
@@ -9042,25 +9101,27 @@ function arabicXeLatexPreamblePkg(twocolumn = false) {
9042
9101
  % save back tick for use - copy paste -> ` + "`";
9043
9102
  }
9044
9103
  function arabicXeLatexPreambleFont(digitsMapping = "arabicdigits") {
9045
- 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");
9104
+ const customFonts = NON_DEFAULT_CHARACTER_FONT_SPECS.filter((font) => font.latexFontCommand && font.latexFontFamily).map((font) => `\\newfontfamily${font.latexFontCommand}${fontOptions(digitsMapping)}{${font.latexFontFamily}}`).join("\n");
9105
+ const mathFontOptions = fontOptions(digitsMapping, false);
9046
9106
  return `
9047
9107
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9048
9108
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9049
- % Toggle between eastern and western digits by changing the Mapping in the below fonts (inside math font as well) between "arabicdigits" and "digits"
9109
+ % Persian digits: Mapping=farsidigits
9110
+ % Arabic-Indic digits: Mapping=arabicdigits
9111
+ % Western digits: omit Mapping entirely
9050
9112
  \\setdefaultlanguage[calendar=gregorian]{arabic} % from polyglossia
9051
- \\setmainfont[Script=Arabic , Mapping=${digitsMapping}]{Amiri}
9113
+ \\setmainfont${fontOptions(digitsMapping)}{Amiri}
9052
9114
  ${customFonts}
9053
- \\newfontfamily\\boldarabic[Script=Arabic,Mapping=${digitsMapping}]{Amiri Bold}
9054
- \\newfontfamily\\italicarabic[Script=Arabic,Mapping=${digitsMapping}]{Amiri Italic}
9115
+ \\newfontfamily\\boldarabic${fontOptions(digitsMapping)}{Amiri Bold}
9116
+ \\newfontfamily\\italicarabic${fontOptions(digitsMapping)}{Amiri Italic}
9055
9117
 
9056
9118
  % for polyglossia url I dont know, sugggested by cursor
9057
- \\newfontfamily\\arabicfonttt[Script=Arabic,Mapping=${digitsMapping}]{Amiri}
9058
- \\newfontfamily\\arabicfontsf[Script=Arabic,Mapping=${digitsMapping}]{Amiri}
9119
+ \\newfontfamily\\arabicfonttt${fontOptions(digitsMapping)}{Amiri}
9120
+ \\newfontfamily\\arabicfontsf${fontOptions(digitsMapping)}{Amiri}
9059
9121
 
9060
9122
 
9061
9123
  % Explicitly set math font to XITS Math
9062
- % Remove "Script=Arabic" to cancel reflected symbols and other RTL symbols
9063
- \\setmathfont[Script=Arabic , Mapping=${digitsMapping}]{XITS Math} % Ensure XITS Math is correctly installed and available
9124
+ \\setmathfont${mathFontOptions}{XITS Math} % Ensure XITS Math is correctly installed and available
9064
9125
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9065
9126
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9066
9127
  `;
@@ -9222,8 +9283,20 @@ function getArabicXeLatexPreamble(digitsMappingOrOptions = "arabicdigits") {
9222
9283
  }
9223
9284
 
9224
9285
  // src/document2/exportLatex.ts
9286
+ function digitsMappingFromDigitForm(digitForm) {
9287
+ if (digitForm === "western") {
9288
+ return "digits";
9289
+ }
9290
+ if (digitForm === "persianIndic") {
9291
+ return "farsidigits";
9292
+ }
9293
+ return "arabicdigits";
9294
+ }
9225
9295
  function mathBodyLatex(token) {
9226
- if (!token.math || token.sourceOwner === "raw" || token.sourceOwner === "editor") {
9296
+ if (token.sourceOwner === "editor") {
9297
+ return stripDisplayMathDelimiters(mirrorBuTeXOperatorsInTex(token.source, { target: "compile" }));
9298
+ }
9299
+ if (!token.math || token.sourceOwner === "raw") {
9227
9300
  return stripDisplayMathDelimiters(token.source);
9228
9301
  }
9229
9302
  const rendered = renderMathNodeLatex(token.math);
@@ -9259,7 +9332,10 @@ ${body}
9259
9332
  \\label{${token.label.trim()}}
9260
9333
  \\end{equation}`;
9261
9334
  }
9262
- if (!token.math || token.sourceOwner === "raw" || token.sourceOwner === "editor") {
9335
+ if (token.sourceOwner === "editor") {
9336
+ return mirrorBuTeXOperatorsInTex(token.source, { target: "compile" });
9337
+ }
9338
+ if (!token.math || token.sourceOwner === "raw") {
9263
9339
  return token.source;
9264
9340
  }
9265
9341
  return renderMathNodeLatex(token.math);
@@ -9377,7 +9453,7 @@ function articleMaketitlePreamble(meta, twocolumn = false) {
9377
9453
  if (meta.authors.trim().length > 0) {
9378
9454
  parts.push(`\\author{${authorLatex(meta.authors)}}`);
9379
9455
  }
9380
- parts.push(`\\date{${formatHijriDate(meta.date, { locale: "ar", digitForm: "arabicIndic" })}}`);
9456
+ parts.push(`\\date{${formatHijriDate(meta.date, { locale: "ar", digitForm: "western" })}}`);
9381
9457
  return parts.join("\n");
9382
9458
  }
9383
9459
  function articleFrontMatterLatex(meta) {
@@ -9409,7 +9485,7 @@ function document2Latex(document2, options = {}) {
9409
9485
  ${body}` : body;
9410
9486
  }
9411
9487
  const preamble = getArabicXeLatexPreamble({
9412
- digitsMapping: options.digitsMapping ?? "arabicdigits",
9488
+ digitsMapping: options.digitsMapping ?? digitsMappingFromDigitForm(options.digitForm),
9413
9489
  twocolumn
9414
9490
  }) + "\n" + articleMaketitlePreamble(meta, twocolumn);
9415
9491
  return `${preamble}
@@ -9665,8 +9741,8 @@ function remapSelectionAfterRangeMove(selection, direction) {
9665
9741
  }
9666
9742
 
9667
9743
  // src/document2/previewModel.ts
9668
- function mathTex(token, equationSide) {
9669
- return mathTokenSourceForSide(token, equationSide);
9744
+ function mathTex(token, equationSide, digitForm) {
9745
+ return mathTokenSourceForSide(token, equationSide, digitForm);
9670
9746
  }
9671
9747
  function previewInlines(field, islands, output, equationSide, document2, previewOptions) {
9672
9748
  return field.tokens.map((token) => {
@@ -9698,7 +9774,7 @@ function previewInlines(field, islands, output, equationSide, document2, preview
9698
9774
  }
9699
9775
  const island = {
9700
9776
  id: token.id,
9701
- tex: mathTex(token, equationSide),
9777
+ tex: mathTex(token, equationSide, previewOptions.digitForm),
9702
9778
  display: token.display,
9703
9779
  output,
9704
9780
  editable: token.editable
@@ -10341,6 +10417,32 @@ function focusArticleMetaPanel(panel) {
10341
10417
  // src/react-document2/ButexDocumentEditor2.tsx
10342
10418
  var import_react13 = require("react");
10343
10419
 
10420
+ // src/debugJson.ts
10421
+ function lineColumnForPosition(text, position) {
10422
+ const before = text.slice(0, Math.max(0, position));
10423
+ const lines = before.split("\n");
10424
+ return {
10425
+ line: lines.length,
10426
+ column: (lines[lines.length - 1]?.length ?? 0) + 1
10427
+ };
10428
+ }
10429
+ function parseJsonDebugInput(text) {
10430
+ try {
10431
+ return { ok: true, value: JSON.parse(text) };
10432
+ } catch (error) {
10433
+ const message = error instanceof Error ? error.message : String(error);
10434
+ const positionMatch = message.match(/position\s+(\d+)/i);
10435
+ if (positionMatch) {
10436
+ const position = Number(positionMatch[1]);
10437
+ if (Number.isFinite(position)) {
10438
+ const location = lineColumnForPosition(text, position);
10439
+ return { ok: false, error: `Invalid JSON at line ${String(location.line)}, column ${String(location.column)}: ${message}` };
10440
+ }
10441
+ }
10442
+ return { ok: false, error: `Invalid JSON: ${message}` };
10443
+ }
10444
+ }
10445
+
10344
10446
  // src/react-document2/BlockEditor.tsx
10345
10447
  var import_react4 = require("react");
10346
10448
 
@@ -10880,6 +10982,7 @@ function MathChip({
10880
10982
  token,
10881
10983
  output = "svg",
10882
10984
  documentDirection = "rtl",
10985
+ digitForm,
10883
10986
  equationSide = "arabic",
10884
10987
  editable = true,
10885
10988
  uiLocale = "ar",
@@ -10891,7 +10994,7 @@ function MathChip({
10891
10994
  onTextInputFromFocus
10892
10995
  }) {
10893
10996
  const messages = document2Messages(uiLocale);
10894
- const tex = mathTokenSourceForSide(token, equationSide);
10997
+ const tex = mathTokenSourceForSide(token, equationSide, digitForm);
10895
10998
  const forwardArrowKey = documentDirection === "rtl" ? "ArrowLeft" : "ArrowRight";
10896
10999
  const backwardArrowKey = documentDirection === "rtl" ? "ArrowRight" : "ArrowLeft";
10897
11000
  const island = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MathIsland, { id: token.id, tex, display: token.display, output });
@@ -11301,6 +11404,7 @@ function InlineField({
11301
11404
  token,
11302
11405
  output: mathOutput,
11303
11406
  equationSide,
11407
+ digitForm,
11304
11408
  editable: editableEquations,
11305
11409
  uiLocale,
11306
11410
  buttonRef: (element) => {
@@ -12845,6 +12949,11 @@ var WIDGET_CHROME_CSS = `
12845
12949
  font-family: ${BUTEX_DIWANI_OUTLINE_FONT_STACK};
12846
12950
  }
12847
12951
 
12952
+ .butex-widget .font-mode-btn--maghribi,
12953
+ .butex-widget .character-font-option--maghribi {
12954
+ font-family: ${BUTEX_MAGHRIBI_FONT_STACK};
12955
+ }
12956
+
12848
12957
  .butex-widget .character-font-options {
12849
12958
  position: absolute;
12850
12959
  z-index: 10;
@@ -13379,6 +13488,36 @@ var WIDGET_CHROME_CSS = `
13379
13488
  background: var(--butex-dev-inset-bg);
13380
13489
  color: var(--butex-dev-inset-fg);
13381
13490
  }
13491
+
13492
+ .butex-widget .debug-json-import {
13493
+ display: grid;
13494
+ gap: 8px;
13495
+ margin-bottom: 10px;
13496
+ }
13497
+
13498
+ .butex-widget .debug-json-import textarea {
13499
+ min-height: 150px;
13500
+ resize: vertical;
13501
+ border: 1px solid var(--butex-dev-inset-border);
13502
+ border-radius: 8px;
13503
+ padding: 8px 10px;
13504
+ direction: ltr;
13505
+ text-align: left;
13506
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
13507
+ font-size: 11px;
13508
+ background: var(--butex-dev-inset-bg);
13509
+ color: var(--butex-dev-inset-fg);
13510
+ }
13511
+
13512
+ .butex-widget .debug-json-error {
13513
+ margin: 0;
13514
+ border: 1px solid rgba(220, 38, 38, 0.45);
13515
+ background: rgba(254, 226, 226, 0.9);
13516
+ color: #991b1b;
13517
+ border-radius: 8px;
13518
+ padding: 8px 10px;
13519
+ white-space: pre-wrap;
13520
+ }
13382
13521
  `.trim();
13383
13522
  var CHROME_STYLE_ID = "butex-widget-chrome-css";
13384
13523
  function injectWidgetChromeCss(doc) {
@@ -13507,6 +13646,7 @@ ${latex || messages.empty}`;
13507
13646
  var ButexEditor = (0, import_react8.forwardRef)(
13508
13647
  function ButexEditor2({ className, debug = false, defaultSide, uiLocale = "ar", initialSession, onSessionChange }, ref) {
13509
13648
  const messages = equationEditorMessages(uiLocale);
13649
+ const debugEnabled = debug || typeof window !== "undefined" && new URLSearchParams(window.location.search).get("debug") === "1";
13510
13650
  const wrapperRef = (0, import_react8.useRef)(null);
13511
13651
  const surfaceRef = (0, import_react8.useRef)(null);
13512
13652
  const inputRef = (0, import_react8.useRef)(null);
@@ -13524,7 +13664,7 @@ var ButexEditor = (0, import_react8.forwardRef)(
13524
13664
  const digitFormBtnRef = (0, import_react8.useRef)(null);
13525
13665
  const runtimeRef = (0, import_react8.useRef)(null);
13526
13666
  const debugRef = (0, import_react8.useRef)(debug);
13527
- debugRef.current = debug;
13667
+ debugRef.current = debugEnabled;
13528
13668
  const uiLocaleRef = (0, import_react8.useRef)(uiLocale);
13529
13669
  uiLocaleRef.current = uiLocale;
13530
13670
  const onSessionChangeRef = (0, import_react8.useRef)(onSessionChange);
@@ -13532,6 +13672,9 @@ var ButexEditor = (0, import_react8.forwardRef)(
13532
13672
  const debugBodyHiddenRef = (0, import_react8.useRef)(false);
13533
13673
  const [debugBodyHidden, setDebugBodyHidden] = (0, import_react8.useState)(false);
13534
13674
  debugBodyHiddenRef.current = debugBodyHidden;
13675
+ const [debugImportOpen, setDebugImportOpen] = (0, import_react8.useState)(false);
13676
+ const [debugImportText, setDebugImportText] = (0, import_react8.useState)("");
13677
+ const [debugImportError, setDebugImportError] = (0, import_react8.useState)("");
13535
13678
  const [digitMenuOpen, setDigitMenuOpen] = (0, import_react8.useState)(false);
13536
13679
  const [characterFontMenuOpen, setCharacterFontMenuOpen] = (0, import_react8.useState)(false);
13537
13680
  const [delimiterMenuOpen, setDelimiterMenuOpen] = (0, import_react8.useState)(false);
@@ -13612,6 +13755,54 @@ ${arabic || currentMessages.empty}`;
13612
13755
  }, []);
13613
13756
  const updatePreviewRef = (0, import_react8.useRef)(updatePreview);
13614
13757
  updatePreviewRef.current = updatePreview;
13758
+ async function copyDebugText(text) {
13759
+ try {
13760
+ await navigator.clipboard.writeText(text);
13761
+ } catch {
13762
+ }
13763
+ }
13764
+ function currentMathObjectJsonText() {
13765
+ const session = runtimeRef.current?.getSession();
13766
+ if (!session) {
13767
+ return "";
13768
+ }
13769
+ const math = mathNodeFromEditorSession(session);
13770
+ if (!math.ok) {
13771
+ return "";
13772
+ }
13773
+ return JSON.stringify(toMathObjectJson(math.math), null, 2);
13774
+ }
13775
+ function openDebugMathObjectImport() {
13776
+ setDebugImportText(currentMathObjectJsonText());
13777
+ setDebugImportError("");
13778
+ setDebugImportOpen(true);
13779
+ }
13780
+ function applyDebugMathObjectImport() {
13781
+ const parsed = parseJsonDebugInput(debugImportText);
13782
+ if (!parsed.ok) {
13783
+ setDebugImportError(parsed.error);
13784
+ return;
13785
+ }
13786
+ try {
13787
+ const math = fromMathObjectJson(parsed.value, activeEditorSide);
13788
+ const result = mathObjectToEditorSession(math);
13789
+ if (!result.editable) {
13790
+ setDebugImportError(result.reason);
13791
+ return;
13792
+ }
13793
+ const next = { ...result.session, activeSide: activeEditorSide };
13794
+ runtimeRef.current?.setSession(next);
13795
+ setSelectedDigitForm(next.currentDigitForm ?? "western");
13796
+ setSelectedCharacterFont(next.currentCharacterFont ?? "default");
13797
+ setActiveEditorSide(next.activeSide);
13798
+ onSessionChangeRef.current?.(next);
13799
+ setDebugImportError("");
13800
+ setDebugImportOpen(false);
13801
+ void updatePreviewRef.current(next);
13802
+ } catch (importError) {
13803
+ setDebugImportError(importError instanceof Error ? importError.message : String(importError));
13804
+ }
13805
+ }
13615
13806
  (0, import_react8.useEffect)(() => {
13616
13807
  injectWidgetChromeCss();
13617
13808
  injectBuTeXEditorStyles(typeof document !== "undefined" ? document : void 0);
@@ -14772,7 +14963,7 @@ ${arabic || currentMessages.empty}`;
14772
14963
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref: renderErrorRef, className: "error", hidden: true })
14773
14964
  ] }),
14774
14965
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("section", { className: "panel panel-preview", "aria-label": messages.renderPreview, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref: mathOutputRef, className: "preview-box" }) }),
14775
- debug ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "panel", children: [
14966
+ debugEnabled ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "panel", children: [
14776
14967
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dev-strip", children: [
14777
14968
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dev-badge", children: messages.development }),
14778
14969
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref: latexLinesRef, className: "ascii" }),
@@ -14780,6 +14971,8 @@ ${arabic || currentMessages.empty}`;
14780
14971
  ] }),
14781
14972
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { marginTop: 12 }, children: [
14782
14973
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "debug-head", children: [
14974
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", onClick: () => void copyDebugText(currentMathObjectJsonText()), children: "Copy MathObject JSON" }),
14975
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", "aria-expanded": debugImportOpen, onClick: openDebugMathObjectImport, children: "Import MathObject JSON" }),
14783
14976
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
14784
14977
  "button",
14785
14978
  {
@@ -14815,6 +15008,35 @@ ${arabic || currentMessages.empty}`;
14815
15008
  }
14816
15009
  )
14817
15010
  ] }),
15011
+ debugImportOpen ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "debug-json-import", children: [
15012
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
15013
+ "textarea",
15014
+ {
15015
+ value: debugImportText,
15016
+ "aria-label": "Import MathObject JSON",
15017
+ spellCheck: false,
15018
+ onChange: (event) => {
15019
+ setDebugImportText(event.currentTarget.value);
15020
+ setDebugImportError("");
15021
+ }
15022
+ }
15023
+ ),
15024
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "debug-head", children: [
15025
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", onClick: applyDebugMathObjectImport, children: "Apply" }),
15026
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
15027
+ "button",
15028
+ {
15029
+ type: "button",
15030
+ onClick: () => {
15031
+ setDebugImportOpen(false);
15032
+ setDebugImportError("");
15033
+ },
15034
+ children: "Cancel"
15035
+ }
15036
+ )
15037
+ ] }),
15038
+ debugImportError ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "debug-json-error", children: debugImportError }) : null
15039
+ ] }) : null,
14818
15040
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref: debugLogRef, className: "debug-log" })
14819
15041
  ] })
14820
15042
  ] }) : null
@@ -14840,6 +15062,7 @@ function keyErrorMessage2(error, messages) {
14840
15062
  return null;
14841
15063
  }
14842
15064
  function EquationDrawer({
15065
+ debug = false,
14843
15066
  session,
14844
15067
  reason,
14845
15068
  mathMode,
@@ -14957,7 +15180,7 @@ function EquationDrawer({
14957
15180
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
14958
15181
  ButexEditor,
14959
15182
  {
14960
- debug: false,
15183
+ debug,
14961
15184
  defaultSide: equationSide,
14962
15185
  uiLocale,
14963
15186
  initialSession: session,
@@ -16539,6 +16762,42 @@ var DOCUMENT2_WIDGET_CSS = `
16539
16762
  white-space: pre-wrap;
16540
16763
  }
16541
16764
 
16765
+ .butex-document2-widget__dev-actions {
16766
+ display: flex;
16767
+ flex-wrap: wrap;
16768
+ gap: 8px;
16769
+ margin: 0 0 10px;
16770
+ }
16771
+
16772
+ .butex-document2-widget__dev-import {
16773
+ display: grid;
16774
+ gap: 8px;
16775
+ margin-bottom: 12px;
16776
+ }
16777
+
16778
+ .butex-document2-widget__dev-import textarea {
16779
+ background: var(--butex-document2-dev-code-bg);
16780
+ border: 1px solid var(--butex-document2-dev-border);
16781
+ border-radius: 8px;
16782
+ color: var(--butex-document2-dev-code-fg);
16783
+ direction: ltr;
16784
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
16785
+ min-height: 180px;
16786
+ padding: 10px;
16787
+ resize: vertical;
16788
+ text-align: left;
16789
+ }
16790
+
16791
+ .butex-document2-widget__dev-error {
16792
+ background: rgba(254, 226, 226, 0.9);
16793
+ border: 1px solid rgba(220, 38, 38, 0.45);
16794
+ border-radius: 8px;
16795
+ color: #991b1b;
16796
+ margin: 0;
16797
+ padding: 8px 10px;
16798
+ white-space: pre-wrap;
16799
+ }
16800
+
16542
16801
  .butex-document2-widget__dev-diagnostic {
16543
16802
  background: rgba(251, 191, 36, 0.18);
16544
16803
  border: 1px solid rgba(217, 119, 6, 0.4);
@@ -17402,11 +17661,17 @@ function ButexDocumentEditor2({
17402
17661
  const [labelsOpen, setLabelsOpen] = (0, import_react13.useState)(false);
17403
17662
  const [refPicker, setRefPicker] = (0, import_react13.useState)(null);
17404
17663
  const [digitFormState, setDigitFormState] = (0, import_react13.useState)(null);
17664
+ const [debugImportOpen, setDebugImportOpen] = (0, import_react13.useState)(false);
17665
+ const [debugImportText, setDebugImportText] = (0, import_react13.useState)("");
17666
+ const [debugImportError, setDebugImportError] = (0, import_react13.useState)("");
17405
17667
  const [editorFocus, setEditorFocus] = (0, import_react13.useState)(createEmptyDocument2EditorFocus());
17406
17668
  const [collapsedBlockIds, setCollapsedBlockIds] = (0, import_react13.useState)(() => /* @__PURE__ */ new Set());
17407
17669
  const [blockSelectionState, setBlockSelectionState] = (0, import_react13.useState)(emptyBlockSelection);
17408
17670
  const [historyTick, setHistoryTick] = (0, import_react13.useState)(0);
17409
17671
  const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
17672
+ function equationSessionWithDocumentDigits(session) {
17673
+ return setCurrentDigitForm(session, digitForm);
17674
+ }
17410
17675
  const historyRef = (0, import_react13.useRef)(createDocument2History());
17411
17676
  const documentRef = (0, import_react13.useRef)(documentNode);
17412
17677
  const textSnapshotArmedRef = (0, import_react13.useRef)(false);
@@ -17415,7 +17680,7 @@ function ButexDocumentEditor2({
17415
17680
  const articleMetaPanelRef = (0, import_react13.useRef)(null);
17416
17681
  const pendingFocusRef = (0, import_react13.useRef)(null);
17417
17682
  documentRef.current = documentNode;
17418
- const latex = document2Latex(documentNode);
17683
+ const latex = document2Latex(documentNode, { digitForm });
17419
17684
  const documentJson = (0, import_react13.useMemo)(() => toDocumentJson2(documentNode), [documentNode]);
17420
17685
  const documentLabels = (0, import_react13.useMemo)(() => collectDocument2Labels(documentNode), [documentNode]);
17421
17686
  const preview = (0, import_react13.useMemo)(
@@ -17623,6 +17888,46 @@ function ButexDocumentEditor2({
17623
17888
  function openAllBlocks() {
17624
17889
  setCollapsedBlockIds(/* @__PURE__ */ new Set());
17625
17890
  }
17891
+ async function copyDebugText(text) {
17892
+ try {
17893
+ await navigator.clipboard.writeText(text);
17894
+ } catch {
17895
+ }
17896
+ }
17897
+ function openDebugJsonImport() {
17898
+ setDebugImportText(JSON.stringify(documentJson, null, 2));
17899
+ setDebugImportError("");
17900
+ setDebugImportOpen(true);
17901
+ }
17902
+ function applyDebugJsonImport() {
17903
+ const parsed = parseJsonDebugInput(debugImportText);
17904
+ if (!parsed.ok) {
17905
+ setDebugImportError(parsed.error);
17906
+ return;
17907
+ }
17908
+ try {
17909
+ const imported = fromDocumentJson2(parsed.value);
17910
+ textSnapshotArmedRef.current = false;
17911
+ if (textDebounceRef.current !== null) {
17912
+ window.clearTimeout(textDebounceRef.current);
17913
+ textDebounceRef.current = null;
17914
+ }
17915
+ setDocumentNode(imported);
17916
+ setError(null);
17917
+ setSelectedMath(null);
17918
+ setCitePicker(null);
17919
+ setRefPicker(null);
17920
+ clearBlockSelection();
17921
+ setCollapsedBlockIds(/* @__PURE__ */ new Set());
17922
+ setEditorFocus(createEmptyDocument2EditorFocus());
17923
+ historyRef.current = createDocument2History();
17924
+ bumpHistoryUi();
17925
+ setDebugImportError("");
17926
+ setDebugImportOpen(false);
17927
+ } catch (importError) {
17928
+ setDebugImportError(importError instanceof Error ? importError.message : String(importError));
17929
+ }
17930
+ }
17626
17931
  (0, import_react13.useEffect)(() => {
17627
17932
  const root = widgetRef.current;
17628
17933
  if (!root) {
@@ -17678,7 +17983,7 @@ function ButexDocumentEditor2({
17678
17983
  textTokenId: target?.textTokenId ?? null,
17679
17984
  insertAt: target?.caretOffset ?? 0,
17680
17985
  mathMode: mode,
17681
- session: createEmptyEquationSession(equationSide),
17986
+ session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
17682
17987
  reason: null,
17683
17988
  labelEnabled: false,
17684
17989
  label: ""
@@ -17698,7 +18003,7 @@ function ButexDocumentEditor2({
17698
18003
  insertAt: 0,
17699
18004
  textTokenId: null,
17700
18005
  mathMode: mode,
17701
- session: createEmptyEquationSession(equationSide),
18006
+ session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
17702
18007
  reason: result.reason,
17703
18008
  labelEnabled: Boolean(token.labelEnabled),
17704
18009
  label: token.label ?? ""
@@ -17711,7 +18016,7 @@ function ButexDocumentEditor2({
17711
18016
  insertAt: 0,
17712
18017
  textTokenId: null,
17713
18018
  mathMode: mode,
17714
- session: result.session,
18019
+ session: equationSessionWithDocumentDigits(result.session),
17715
18020
  reason: null,
17716
18021
  labelEnabled: Boolean(token.labelEnabled),
17717
18022
  label: token.label ?? ""
@@ -18136,14 +18441,51 @@ function ButexDocumentEditor2({
18136
18441
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: messages.importWarnings }),
18137
18442
  documentNode.diagnostics.map((diagnostic) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "butex-document2-widget__dev-diagnostic", children: formatDocument2Diagnostic(diagnostic, messages) }, `${diagnostic.path}-${diagnostic.message}`))
18138
18443
  ] }) : null,
18444
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__dev-actions", children: [
18445
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: () => void copyDebugText(JSON.stringify(documentJson, null, 2)), children: "Copy JSON" }),
18446
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: () => void copyDebugText(latex), children: "Copy TeX" }),
18447
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", "aria-expanded": debugImportOpen, onClick: openDebugJsonImport, children: "Import JSON" })
18448
+ ] }),
18449
+ debugImportOpen ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__dev-import", children: [
18450
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18451
+ "textarea",
18452
+ {
18453
+ value: debugImportText,
18454
+ "aria-label": "Import Document2 JSON",
18455
+ spellCheck: false,
18456
+ onChange: (event) => {
18457
+ setDebugImportText(event.currentTarget.value);
18458
+ setDebugImportError("");
18459
+ }
18460
+ }
18461
+ ),
18462
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__dev-actions", children: [
18463
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: applyDebugJsonImport, children: "Apply" }),
18464
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18465
+ "button",
18466
+ {
18467
+ type: "button",
18468
+ onClick: () => {
18469
+ setDebugImportOpen(false);
18470
+ setDebugImportError("");
18471
+ },
18472
+ children: "Cancel"
18473
+ }
18474
+ )
18475
+ ] }),
18476
+ debugImportError ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "butex-document2-widget__dev-error", children: debugImportError }) : null
18477
+ ] }) : null,
18139
18478
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "LaTeX" }),
18140
18479
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pre", { children: latex }),
18480
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "JSON" }),
18481
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pre", { children: JSON.stringify(documentJson, null, 2) }),
18141
18482
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "AST" }),
18142
18483
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pre", { children: JSON.stringify(documentNode, null, 2) })
18143
18484
  ] }) : null,
18144
18485
  !previewOnly && selectedMath ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18145
18486
  EquationDrawer,
18146
18487
  {
18488
+ debug: debugEnabled,
18147
18489
  session: selectedMath.session,
18148
18490
  reason: selectedMath.reason,
18149
18491
  mathMode: selectedMath.mathMode,