@drghaliasri/butex 5.5.5 → 5.6.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.
@@ -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);
@@ -17369,868 +17628,977 @@ function resolveInitialDocument2(initialDocument, uiLocale = "ar", documentMeta)
17369
17628
  };
17370
17629
  }
17371
17630
  }
17372
- function ButexDocumentEditor2({
17373
- initialDocument,
17374
- documentMeta,
17375
- className,
17376
- debug = false,
17377
- documentDirection = "rtl",
17378
- equationSide = "arabic",
17379
- editableEquations = true,
17380
- previewOnly = false,
17381
- uiLocale = "ar",
17382
- mathOutput = "svg",
17383
- digitForm: digitFormProp,
17384
- onDigitFormChange,
17385
- resolveImageUrl,
17386
- onDocumentChange,
17387
- onDocumentJsonChange,
17388
- onLatexChange
17389
- }) {
17390
- const messages = document2Messages(uiLocale);
17391
- const initialState = (0, import_react13.useMemo)(
17392
- () => resolveInitialDocument2(initialDocument, uiLocale, documentMeta),
17393
- [initialDocument, documentMeta, uiLocale]
17394
- );
17395
- const [documentNode, setDocumentNode] = (0, import_react13.useState)(initialState.document);
17396
- const [error, setError] = (0, import_react13.useState)(initialState.error);
17397
- const [editorOpen, setEditorOpen] = (0, import_react13.useState)(true);
17398
- const [previewOpen, setPreviewOpen] = (0, import_react13.useState)(true);
17399
- const [selectedMath, setSelectedMath] = (0, import_react13.useState)(null);
17400
- const [citePicker, setCitePicker] = (0, import_react13.useState)(null);
17401
- const [referencesOpen, setReferencesOpen] = (0, import_react13.useState)(false);
17402
- const [labelsOpen, setLabelsOpen] = (0, import_react13.useState)(false);
17403
- const [refPicker, setRefPicker] = (0, import_react13.useState)(null);
17404
- const [digitFormState, setDigitFormState] = (0, import_react13.useState)(null);
17405
- const [editorFocus, setEditorFocus] = (0, import_react13.useState)(createEmptyDocument2EditorFocus());
17406
- const [collapsedBlockIds, setCollapsedBlockIds] = (0, import_react13.useState)(() => /* @__PURE__ */ new Set());
17407
- const [blockSelectionState, setBlockSelectionState] = (0, import_react13.useState)(emptyBlockSelection);
17408
- const [historyTick, setHistoryTick] = (0, import_react13.useState)(0);
17409
- const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
17410
- const historyRef = (0, import_react13.useRef)(createDocument2History());
17411
- const documentRef = (0, import_react13.useRef)(documentNode);
17412
- const textSnapshotArmedRef = (0, import_react13.useRef)(false);
17413
- const textDebounceRef = (0, import_react13.useRef)(null);
17414
- const widgetRef = (0, import_react13.useRef)(null);
17415
- const articleMetaPanelRef = (0, import_react13.useRef)(null);
17416
- const pendingFocusRef = (0, import_react13.useRef)(null);
17417
- documentRef.current = documentNode;
17418
- const latex = document2Latex(documentNode);
17419
- const documentJson = (0, import_react13.useMemo)(() => toDocumentJson2(documentNode), [documentNode]);
17420
- const documentLabels = (0, import_react13.useMemo)(() => collectDocument2Labels(documentNode), [documentNode]);
17421
- const preview = (0, import_react13.useMemo)(
17422
- () => document2Preview(documentNode, mathOutput, equationSide, {
17423
- documentDirection,
17424
- digitForm,
17425
- uiLocale
17426
- }),
17427
- [documentNode, documentDirection, digitForm, equationSide, mathOutput, uiLocale]
17428
- );
17429
- const debugEnabled = (0, import_react13.useMemo)(() => {
17430
- if (debug) {
17431
- return true;
17432
- }
17433
- if (typeof window === "undefined") {
17434
- return false;
17435
- }
17436
- return new URLSearchParams(window.location.search).get("debug") === "1";
17437
- }, [debug]);
17438
- const canUndo = (0, import_react13.useMemo)(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
17439
- const canRedo = (0, import_react13.useMemo)(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
17440
- const blockSelection = normalizeBlockSelection(blockSelectionState.selection, documentNode.blocks.length);
17441
- const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
17442
- const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
17443
- const canMoveSelectionDown = Boolean(blockSelection && blockSelection.to < documentNode.blocks.length - 1);
17444
- const formatTextToken = (0, import_react13.useMemo)(() => findFormatTextToken(documentNode, editorFocus), [documentNode, editorFocus]);
17445
- const canFormatText = formatTextToken !== null;
17446
- const activeTextStyles = formatTextToken?.style ?? {};
17447
- function clearBlockSelection() {
17448
- setBlockSelectionState(emptyBlockSelection());
17449
- }
17450
- function toggleSelectBlock(blockId, shiftKey) {
17451
- const index = documentRef.current.blocks.findIndex((block) => block.id === blockId);
17452
- if (index < 0) {
17453
- return;
17454
- }
17455
- const blockCount = documentRef.current.blocks.length;
17456
- setBlockSelectionState(
17457
- (current) => shiftKey ? extendBlockSelectionFromAnchor(current, index, blockCount) : toggleBlockInSelection(current, index, blockCount)
17631
+ var ButexDocumentEditor2 = (0, import_react13.forwardRef)(
17632
+ function ButexDocumentEditor22({
17633
+ initialDocument,
17634
+ documentMeta,
17635
+ className,
17636
+ debug = false,
17637
+ documentDirection = "rtl",
17638
+ equationSide = "arabic",
17639
+ editableEquations = true,
17640
+ previewOnly = false,
17641
+ uiLocale = "ar",
17642
+ mathOutput = "svg",
17643
+ digitForm: digitFormProp,
17644
+ onDigitFormChange,
17645
+ resolveImageUrl,
17646
+ onDocumentChange,
17647
+ onDocumentJsonChange,
17648
+ onLatexChange
17649
+ }, ref) {
17650
+ const messages = document2Messages(uiLocale);
17651
+ const initialState = (0, import_react13.useMemo)(
17652
+ () => resolveInitialDocument2(initialDocument, uiLocale, documentMeta),
17653
+ [initialDocument, documentMeta, uiLocale]
17458
17654
  );
17459
- }
17460
- function moveSelectedBlocks(direction) {
17461
- const selection = normalizeBlockSelection(blockSelectionState.selection, documentRef.current.blocks.length);
17462
- if (!selection) {
17463
- return;
17655
+ const [documentNode, setDocumentNode] = (0, import_react13.useState)(initialState.document);
17656
+ const [error, setError] = (0, import_react13.useState)(initialState.error);
17657
+ const [editorOpen, setEditorOpen] = (0, import_react13.useState)(true);
17658
+ const [previewOpen, setPreviewOpen] = (0, import_react13.useState)(true);
17659
+ const [selectedMath, setSelectedMath] = (0, import_react13.useState)(null);
17660
+ const [citePicker, setCitePicker] = (0, import_react13.useState)(null);
17661
+ const [referencesOpen, setReferencesOpen] = (0, import_react13.useState)(false);
17662
+ const [labelsOpen, setLabelsOpen] = (0, import_react13.useState)(false);
17663
+ const [refPicker, setRefPicker] = (0, import_react13.useState)(null);
17664
+ const [digitFormState, setDigitFormState] = (0, import_react13.useState)(null);
17665
+ const [debugImportOpen, setDebugImportOpen] = (0, import_react13.useState)(false);
17666
+ const [debugImportText, setDebugImportText] = (0, import_react13.useState)("");
17667
+ const [debugImportError, setDebugImportError] = (0, import_react13.useState)("");
17668
+ const [editorFocus, setEditorFocus] = (0, import_react13.useState)(createEmptyDocument2EditorFocus());
17669
+ const [collapsedBlockIds, setCollapsedBlockIds] = (0, import_react13.useState)(() => /* @__PURE__ */ new Set());
17670
+ const [blockSelectionState, setBlockSelectionState] = (0, import_react13.useState)(emptyBlockSelection);
17671
+ const [historyTick, setHistoryTick] = (0, import_react13.useState)(0);
17672
+ const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
17673
+ function equationSessionWithDocumentDigits(session) {
17674
+ return setCurrentDigitForm(session, digitForm);
17675
+ }
17676
+ const historyRef = (0, import_react13.useRef)(createDocument2History());
17677
+ const documentRef = (0, import_react13.useRef)(documentNode);
17678
+ const editorFocusRef = (0, import_react13.useRef)(editorFocus);
17679
+ const textSnapshotArmedRef = (0, import_react13.useRef)(false);
17680
+ const textDebounceRef = (0, import_react13.useRef)(null);
17681
+ const widgetRef = (0, import_react13.useRef)(null);
17682
+ const articleMetaPanelRef = (0, import_react13.useRef)(null);
17683
+ const pendingFocusRef = (0, import_react13.useRef)(null);
17684
+ documentRef.current = documentNode;
17685
+ editorFocusRef.current = editorFocus;
17686
+ const latex = document2Latex(documentNode, { digitForm });
17687
+ const documentJson = (0, import_react13.useMemo)(() => toDocumentJson2(documentNode), [documentNode]);
17688
+ const documentLabels = (0, import_react13.useMemo)(() => collectDocument2Labels(documentNode), [documentNode]);
17689
+ const preview = (0, import_react13.useMemo)(
17690
+ () => document2Preview(documentNode, mathOutput, equationSide, {
17691
+ documentDirection,
17692
+ digitForm,
17693
+ uiLocale
17694
+ }),
17695
+ [documentNode, documentDirection, digitForm, equationSide, mathOutput, uiLocale]
17696
+ );
17697
+ const debugEnabled = (0, import_react13.useMemo)(() => {
17698
+ if (debug) {
17699
+ return true;
17700
+ }
17701
+ if (typeof window === "undefined") {
17702
+ return false;
17703
+ }
17704
+ return new URLSearchParams(window.location.search).get("debug") === "1";
17705
+ }, [debug]);
17706
+ const canUndo = (0, import_react13.useMemo)(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
17707
+ const canRedo = (0, import_react13.useMemo)(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
17708
+ const blockSelection = normalizeBlockSelection(blockSelectionState.selection, documentNode.blocks.length);
17709
+ const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
17710
+ const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
17711
+ const canMoveSelectionDown = Boolean(blockSelection && blockSelection.to < documentNode.blocks.length - 1);
17712
+ const formatTextToken = (0, import_react13.useMemo)(() => findFormatTextToken(documentNode, editorFocus), [documentNode, editorFocus]);
17713
+ const canFormatText = formatTextToken !== null;
17714
+ const activeTextStyles = formatTextToken?.style ?? {};
17715
+ function clearBlockSelection() {
17716
+ setBlockSelectionState(emptyBlockSelection());
17717
+ }
17718
+ function toggleSelectBlock(blockId, shiftKey) {
17719
+ const index = documentRef.current.blocks.findIndex((block) => block.id === blockId);
17720
+ if (index < 0) {
17721
+ return;
17722
+ }
17723
+ const blockCount = documentRef.current.blocks.length;
17724
+ setBlockSelectionState(
17725
+ (current) => shiftKey ? extendBlockSelectionFromAnchor(current, index, blockCount) : toggleBlockInSelection(current, index, blockCount)
17726
+ );
17464
17727
  }
17465
- const next = moveDocument2BlockRange(documentRef.current, selection.from, selection.to, direction);
17466
- if (next === documentRef.current) {
17467
- return;
17728
+ function moveSelectedBlocks(direction) {
17729
+ const selection = normalizeBlockSelection(blockSelectionState.selection, documentRef.current.blocks.length);
17730
+ if (!selection) {
17731
+ return;
17732
+ }
17733
+ const next = moveDocument2BlockRange(documentRef.current, selection.from, selection.to, direction);
17734
+ if (next === documentRef.current) {
17735
+ return;
17736
+ }
17737
+ applyDocument(next, "immediate");
17738
+ const remapped = remapSelectionAfterRangeMove(selection, direction);
17739
+ setBlockSelectionState({
17740
+ selection: normalizeBlockSelection(remapped, next.blocks.length),
17741
+ anchor: blockSelectionState.anchor === null ? null : blockSelectionState.anchor + direction
17742
+ });
17468
17743
  }
17469
- applyDocument(next, "immediate");
17470
- const remapped = remapSelectionAfterRangeMove(selection, direction);
17471
- setBlockSelectionState({
17472
- selection: normalizeBlockSelection(remapped, next.blocks.length),
17473
- anchor: blockSelectionState.anchor === null ? null : blockSelectionState.anchor + direction
17474
- });
17475
- }
17476
- function deleteSelectedBlocks() {
17477
- const selection = normalizeBlockSelection(blockSelectionState.selection, documentRef.current.blocks.length);
17478
- if (!selection) {
17479
- return;
17744
+ function deleteSelectedBlocks() {
17745
+ const selection = normalizeBlockSelection(blockSelectionState.selection, documentRef.current.blocks.length);
17746
+ if (!selection) {
17747
+ return;
17748
+ }
17749
+ applyDocument(removeDocument2BlockRange(documentRef.current, selection.from, selection.to), "immediate");
17750
+ clearBlockSelection();
17480
17751
  }
17481
- applyDocument(removeDocument2BlockRange(documentRef.current, selection.from, selection.to), "immediate");
17482
- clearBlockSelection();
17483
- }
17484
- (0, import_react13.useEffect)(() => {
17485
- injectBuTeXDocument2Styles();
17486
- }, []);
17487
- (0, import_react13.useEffect)(() => {
17488
- if (!editableEquations || previewOnly) {
17752
+ (0, import_react13.useEffect)(() => {
17753
+ injectBuTeXDocument2Styles();
17754
+ }, []);
17755
+ (0, import_react13.useEffect)(() => {
17756
+ if (!editableEquations || previewOnly) {
17757
+ setSelectedMath(null);
17758
+ }
17759
+ }, [editableEquations, previewOnly]);
17760
+ (0, import_react13.useEffect)(() => {
17761
+ const next = resolveInitialDocument2(initialDocument, uiLocale, documentMeta);
17762
+ setDocumentNode(next.document);
17763
+ setError(next.error);
17489
17764
  setSelectedMath(null);
17490
- }
17491
- }, [editableEquations, previewOnly]);
17492
- (0, import_react13.useEffect)(() => {
17493
- const next = resolveInitialDocument2(initialDocument, uiLocale, documentMeta);
17494
- setDocumentNode(next.document);
17495
- setError(next.error);
17496
- setSelectedMath(null);
17497
- setCollapsedBlockIds(/* @__PURE__ */ new Set());
17498
- historyRef.current = createDocument2History();
17499
- setHistoryTick((tick) => tick + 1);
17500
- }, [initialDocument, documentMeta, uiLocale]);
17501
- (0, import_react13.useEffect)(() => {
17502
- onDocumentChange?.(documentNode);
17503
- }, [documentNode, onDocumentChange]);
17504
- (0, import_react13.useEffect)(() => {
17505
- onDocumentJsonChange?.(documentJson);
17506
- }, [documentJson, onDocumentJsonChange]);
17507
- (0, import_react13.useEffect)(() => {
17508
- onLatexChange?.(latex);
17509
- }, [latex, onLatexChange]);
17510
- (0, import_react13.useEffect)(() => {
17511
- const pending = pendingFocusRef.current;
17512
- const root = widgetRef.current;
17513
- if (!pending || !root) {
17514
- return;
17515
- }
17516
- pendingFocusRef.current = null;
17517
- requestAnimationFrame(() => {
17518
- if (pending.kind === "math") {
17519
- const mathButton = Array.from(root.querySelectorAll("[data-math-token-id]")).find(
17520
- (button) => button.dataset.mathTokenId === pending.tokenId
17521
- );
17522
- mathButton?.focus();
17765
+ setCollapsedBlockIds(/* @__PURE__ */ new Set());
17766
+ historyRef.current = createDocument2History();
17767
+ setHistoryTick((tick) => tick + 1);
17768
+ }, [initialDocument, documentMeta, uiLocale]);
17769
+ (0, import_react13.useEffect)(() => {
17770
+ onDocumentChange?.(documentNode);
17771
+ }, [documentNode, onDocumentChange]);
17772
+ (0, import_react13.useEffect)(() => {
17773
+ onDocumentJsonChange?.(documentJson);
17774
+ }, [documentJson, onDocumentJsonChange]);
17775
+ (0, import_react13.useEffect)(() => {
17776
+ onLatexChange?.(latex);
17777
+ }, [latex, onLatexChange]);
17778
+ (0, import_react13.useEffect)(() => {
17779
+ const pending = pendingFocusRef.current;
17780
+ const root = widgetRef.current;
17781
+ if (!pending || !root) {
17523
17782
  return;
17524
17783
  }
17525
- if (pending.kind === "cite") {
17526
- const citeButton = Array.from(root.querySelectorAll("[data-cite-token-id]")).find(
17527
- (button) => button.dataset.citeTokenId === pending.tokenId
17784
+ pendingFocusRef.current = null;
17785
+ requestAnimationFrame(() => {
17786
+ if (pending.kind === "math") {
17787
+ const mathButton = Array.from(root.querySelectorAll("[data-math-token-id]")).find(
17788
+ (button) => button.dataset.mathTokenId === pending.tokenId
17789
+ );
17790
+ mathButton?.focus();
17791
+ return;
17792
+ }
17793
+ if (pending.kind === "cite") {
17794
+ const citeButton = Array.from(root.querySelectorAll("[data-cite-token-id]")).find(
17795
+ (button) => button.dataset.citeTokenId === pending.tokenId
17796
+ );
17797
+ citeButton?.focus();
17798
+ return;
17799
+ }
17800
+ if (pending.kind === "ref") {
17801
+ const refButton = Array.from(root.querySelectorAll("[data-ref-token-id]")).find(
17802
+ (button) => button.dataset.refTokenId === pending.tokenId
17803
+ );
17804
+ refButton?.focus();
17805
+ return;
17806
+ }
17807
+ const textarea = Array.from(root.querySelectorAll("textarea[data-field-id][data-text-token-id]")).find(
17808
+ (element) => element.dataset.fieldId === pending.fieldId && element.dataset.textTokenId === pending.textTokenId
17528
17809
  );
17529
- citeButton?.focus();
17810
+ if (!textarea) {
17811
+ return;
17812
+ }
17813
+ const safeOffset = Math.max(0, Math.min(pending.caretOffset, textarea.value.length));
17814
+ textarea.focus();
17815
+ textarea.setSelectionRange(safeOffset, safeOffset);
17816
+ });
17817
+ }, [documentNode]);
17818
+ const bumpHistoryUi = (0, import_react13.useCallback)(() => {
17819
+ setHistoryTick((tick) => tick + 1);
17820
+ }, []);
17821
+ const applyDocument = (0, import_react13.useCallback)(
17822
+ (next, mode = "immediate") => {
17823
+ if (mode === "immediate") {
17824
+ pushDocument2Snapshot(historyRef.current, documentRef.current);
17825
+ bumpHistoryUi();
17826
+ } else if (mode === "text") {
17827
+ if (!textSnapshotArmedRef.current) {
17828
+ pushDocument2Snapshot(historyRef.current, documentRef.current);
17829
+ textSnapshotArmedRef.current = true;
17830
+ bumpHistoryUi();
17831
+ }
17832
+ if (textDebounceRef.current !== null) {
17833
+ window.clearTimeout(textDebounceRef.current);
17834
+ }
17835
+ textDebounceRef.current = window.setTimeout(() => {
17836
+ textSnapshotArmedRef.current = false;
17837
+ }, 400);
17838
+ }
17839
+ documentRef.current = next;
17840
+ setDocumentNode(next);
17841
+ },
17842
+ [bumpHistoryUi]
17843
+ );
17844
+ const afterBlockId = (0, import_react13.useCallback)(() => resolveInsertAfterBlockId(documentRef.current, editorFocusRef.current), []);
17845
+ const insertImageBlock = (0, import_react13.useCallback)(
17846
+ (srcOrAssetId = "") => {
17847
+ clearBlockSelection();
17848
+ const after = resolveInsertAfterBlockId(documentRef.current, editorFocusRef.current);
17849
+ applyDocument(addDocument2ImageBlock(documentRef.current, srcOrAssetId, after), "immediate");
17850
+ },
17851
+ [applyDocument]
17852
+ );
17853
+ (0, import_react13.useImperativeHandle)(
17854
+ ref,
17855
+ () => ({
17856
+ insertImageBlock,
17857
+ updateImageBlockValue(blockId, value) {
17858
+ applyDocument(updateDocument2ImageValue(documentRef.current, blockId, value), "immediate");
17859
+ },
17860
+ getDocumentJson() {
17861
+ return toDocumentJson2(documentRef.current);
17862
+ }
17863
+ }),
17864
+ [applyDocument, insertImageBlock]
17865
+ );
17866
+ function undoDocument() {
17867
+ const restored = restoreDocument2Undo(historyRef.current, documentRef.current);
17868
+ if (!restored) {
17530
17869
  return;
17531
17870
  }
17532
- if (pending.kind === "ref") {
17533
- const refButton = Array.from(root.querySelectorAll("[data-ref-token-id]")).find(
17534
- (button) => button.dataset.refTokenId === pending.tokenId
17535
- );
17536
- refButton?.focus();
17871
+ textSnapshotArmedRef.current = false;
17872
+ clearBlockSelection();
17873
+ documentRef.current = restored;
17874
+ setDocumentNode(restored);
17875
+ bumpHistoryUi();
17876
+ }
17877
+ function redoDocument() {
17878
+ const restored = restoreDocument2Redo(historyRef.current, documentRef.current);
17879
+ if (!restored) {
17537
17880
  return;
17538
17881
  }
17539
- const textarea = Array.from(root.querySelectorAll("textarea[data-field-id][data-text-token-id]")).find(
17540
- (element) => element.dataset.fieldId === pending.fieldId && element.dataset.textTokenId === pending.textTokenId
17541
- );
17542
- if (!textarea) {
17882
+ textSnapshotArmedRef.current = false;
17883
+ clearBlockSelection();
17884
+ documentRef.current = restored;
17885
+ setDocumentNode(restored);
17886
+ bumpHistoryUi();
17887
+ }
17888
+ function openBlock(blockId) {
17889
+ if (!blockId) {
17543
17890
  return;
17544
17891
  }
17545
- const safeOffset = Math.max(0, Math.min(pending.caretOffset, textarea.value.length));
17546
- textarea.focus();
17547
- textarea.setSelectionRange(safeOffset, safeOffset);
17548
- });
17549
- }, [documentNode]);
17550
- const bumpHistoryUi = (0, import_react13.useCallback)(() => {
17551
- setHistoryTick((tick) => tick + 1);
17552
- }, []);
17553
- const applyDocument = (0, import_react13.useCallback)(
17554
- (next, mode = "immediate") => {
17555
- if (mode === "immediate") {
17556
- pushDocument2Snapshot(historyRef.current, documentRef.current);
17557
- bumpHistoryUi();
17558
- } else if (mode === "text") {
17559
- if (!textSnapshotArmedRef.current) {
17560
- pushDocument2Snapshot(historyRef.current, documentRef.current);
17561
- textSnapshotArmedRef.current = true;
17562
- bumpHistoryUi();
17892
+ setCollapsedBlockIds((current) => {
17893
+ if (!current.has(blockId)) {
17894
+ return current;
17563
17895
  }
17564
- if (textDebounceRef.current !== null) {
17565
- window.clearTimeout(textDebounceRef.current);
17896
+ const next = new Set(current);
17897
+ next.delete(blockId);
17898
+ return next;
17899
+ });
17900
+ }
17901
+ function toggleBlockCollapse(blockId) {
17902
+ setCollapsedBlockIds((current) => {
17903
+ const next = new Set(current);
17904
+ if (next.has(blockId)) {
17905
+ next.delete(blockId);
17906
+ } else {
17907
+ next.add(blockId);
17566
17908
  }
17567
- textDebounceRef.current = window.setTimeout(() => {
17568
- textSnapshotArmedRef.current = false;
17569
- }, 400);
17570
- }
17571
- setDocumentNode(next);
17572
- },
17573
- [bumpHistoryUi]
17574
- );
17575
- const afterBlockId = (0, import_react13.useCallback)(() => resolveInsertAfterBlockId(documentRef.current, editorFocus), [editorFocus]);
17576
- function undoDocument() {
17577
- const restored = restoreDocument2Undo(historyRef.current, documentRef.current);
17578
- if (!restored) {
17579
- return;
17909
+ return next;
17910
+ });
17580
17911
  }
17581
- textSnapshotArmedRef.current = false;
17582
- clearBlockSelection();
17583
- setDocumentNode(restored);
17584
- bumpHistoryUi();
17585
- }
17586
- function redoDocument() {
17587
- const restored = restoreDocument2Redo(historyRef.current, documentRef.current);
17588
- if (!restored) {
17589
- return;
17912
+ function collapseAllBlocks() {
17913
+ setCollapsedBlockIds(new Set(documentRef.current.blocks.map((block) => block.id)));
17590
17914
  }
17591
- textSnapshotArmedRef.current = false;
17592
- clearBlockSelection();
17593
- setDocumentNode(restored);
17594
- bumpHistoryUi();
17595
- }
17596
- function openBlock(blockId) {
17597
- if (!blockId) {
17598
- return;
17915
+ function openAllBlocks() {
17916
+ setCollapsedBlockIds(/* @__PURE__ */ new Set());
17599
17917
  }
17600
- setCollapsedBlockIds((current) => {
17601
- if (!current.has(blockId)) {
17602
- return current;
17918
+ async function copyDebugText(text) {
17919
+ try {
17920
+ await navigator.clipboard.writeText(text);
17921
+ } catch {
17603
17922
  }
17604
- const next = new Set(current);
17605
- next.delete(blockId);
17606
- return next;
17607
- });
17608
- }
17609
- function toggleBlockCollapse(blockId) {
17610
- setCollapsedBlockIds((current) => {
17611
- const next = new Set(current);
17612
- if (next.has(blockId)) {
17613
- next.delete(blockId);
17614
- } else {
17615
- next.add(blockId);
17923
+ }
17924
+ function openDebugJsonImport() {
17925
+ setDebugImportText(JSON.stringify(documentJson, null, 2));
17926
+ setDebugImportError("");
17927
+ setDebugImportOpen(true);
17928
+ }
17929
+ function applyDebugJsonImport() {
17930
+ const parsed = parseJsonDebugInput(debugImportText);
17931
+ if (!parsed.ok) {
17932
+ setDebugImportError(parsed.error);
17933
+ return;
17934
+ }
17935
+ try {
17936
+ const imported = fromDocumentJson2(parsed.value);
17937
+ textSnapshotArmedRef.current = false;
17938
+ if (textDebounceRef.current !== null) {
17939
+ window.clearTimeout(textDebounceRef.current);
17940
+ textDebounceRef.current = null;
17941
+ }
17942
+ setDocumentNode(imported);
17943
+ setError(null);
17944
+ setSelectedMath(null);
17945
+ setCitePicker(null);
17946
+ setRefPicker(null);
17947
+ clearBlockSelection();
17948
+ setCollapsedBlockIds(/* @__PURE__ */ new Set());
17949
+ setEditorFocus(createEmptyDocument2EditorFocus());
17950
+ historyRef.current = createDocument2History();
17951
+ bumpHistoryUi();
17952
+ setDebugImportError("");
17953
+ setDebugImportOpen(false);
17954
+ } catch (importError) {
17955
+ setDebugImportError(importError instanceof Error ? importError.message : String(importError));
17616
17956
  }
17617
- return next;
17618
- });
17619
- }
17620
- function collapseAllBlocks() {
17621
- setCollapsedBlockIds(new Set(documentRef.current.blocks.map((block) => block.id)));
17622
- }
17623
- function openAllBlocks() {
17624
- setCollapsedBlockIds(/* @__PURE__ */ new Set());
17625
- }
17626
- (0, import_react13.useEffect)(() => {
17627
- const root = widgetRef.current;
17628
- if (!root) {
17629
- return;
17630
17957
  }
17631
- const onKeyDown = (event) => {
17632
- if (!editorOpen) {
17958
+ (0, import_react13.useEffect)(() => {
17959
+ const root = widgetRef.current;
17960
+ if (!root) {
17633
17961
  return;
17634
17962
  }
17635
- const mod = event.ctrlKey || event.metaKey;
17636
- if (!mod) {
17963
+ const onKeyDown = (event) => {
17964
+ if (!editorOpen) {
17965
+ return;
17966
+ }
17967
+ const mod = event.ctrlKey || event.metaKey;
17968
+ if (!mod) {
17969
+ return;
17970
+ }
17971
+ if (event.key.toLowerCase() === "z" && !event.shiftKey) {
17972
+ event.preventDefault();
17973
+ undoDocument();
17974
+ } else if (event.key.toLowerCase() === "z" && event.shiftKey || event.key.toLowerCase() === "y") {
17975
+ event.preventDefault();
17976
+ redoDocument();
17977
+ }
17978
+ };
17979
+ root.addEventListener("keydown", onKeyDown);
17980
+ return () => root.removeEventListener("keydown", onKeyDown);
17981
+ }, [editorOpen]);
17982
+ function rememberFieldFocus(blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd) {
17983
+ openBlock(blockId);
17984
+ clearBlockSelection();
17985
+ setEditorFocus({ blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd });
17986
+ }
17987
+ function rememberMathFocus(blockId, fieldId) {
17988
+ openBlock(blockId);
17989
+ clearBlockSelection();
17990
+ setEditorFocus({ blockId, fieldId, textTokenId: null, caretOffset: 0, selectionStart: 0, selectionEnd: 0 });
17991
+ }
17992
+ function rememberBlockFocus(blockId) {
17993
+ openBlock(blockId);
17994
+ setEditorFocus((current) => ({ ...current, blockId }));
17995
+ }
17996
+ function onFieldBlur() {
17997
+ textSnapshotArmedRef.current = false;
17998
+ }
17999
+ function openNewEquation(mode) {
18000
+ if (!editableEquations) {
17637
18001
  return;
17638
18002
  }
17639
- if (event.key.toLowerCase() === "z" && !event.shiftKey) {
17640
- event.preventDefault();
17641
- undoDocument();
17642
- } else if (event.key.toLowerCase() === "z" && event.shiftKey || event.key.toLowerCase() === "y") {
17643
- event.preventDefault();
17644
- redoDocument();
18003
+ const target = resolveInsertField(documentRef.current, editorFocus);
18004
+ if (target?.fieldId) {
18005
+ openBlock(topLevelBlockIdForField(documentRef.current, target.fieldId));
17645
18006
  }
17646
- };
17647
- root.addEventListener("keydown", onKeyDown);
17648
- return () => root.removeEventListener("keydown", onKeyDown);
17649
- }, [editorOpen]);
17650
- function rememberFieldFocus(blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd) {
17651
- openBlock(blockId);
17652
- clearBlockSelection();
17653
- setEditorFocus({ blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd });
17654
- }
17655
- function rememberMathFocus(blockId, fieldId) {
17656
- openBlock(blockId);
17657
- clearBlockSelection();
17658
- setEditorFocus({ blockId, fieldId, textTokenId: null, caretOffset: 0, selectionStart: 0, selectionEnd: 0 });
17659
- }
17660
- function rememberBlockFocus(blockId) {
17661
- openBlock(blockId);
17662
- setEditorFocus((current) => ({ ...current, blockId }));
17663
- }
17664
- function onFieldBlur() {
17665
- textSnapshotArmedRef.current = false;
17666
- }
17667
- function openNewEquation(mode) {
17668
- if (!editableEquations) {
17669
- return;
17670
- }
17671
- const target = resolveInsertField(documentRef.current, editorFocus);
17672
- if (target?.fieldId) {
17673
- openBlock(topLevelBlockIdForField(documentRef.current, target.fieldId));
17674
- }
17675
- setSelectedMath({
17676
- tokenId: null,
17677
- fieldId: target?.fieldId ?? null,
17678
- textTokenId: target?.textTokenId ?? null,
17679
- insertAt: target?.caretOffset ?? 0,
17680
- mathMode: mode,
17681
- session: createEmptyEquationSession(equationSide),
17682
- reason: null,
17683
- labelEnabled: false,
17684
- label: ""
17685
- });
17686
- }
17687
- function openMath(token) {
17688
- if (!editableEquations) {
17689
- return;
18007
+ setSelectedMath({
18008
+ tokenId: null,
18009
+ fieldId: target?.fieldId ?? null,
18010
+ textTokenId: target?.textTokenId ?? null,
18011
+ insertAt: target?.caretOffset ?? 0,
18012
+ mathMode: mode,
18013
+ session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
18014
+ reason: null,
18015
+ labelEnabled: false,
18016
+ label: ""
18017
+ });
17690
18018
  }
17691
- openBlock(topLevelBlockIdForToken(documentRef.current, token.id));
17692
- const result = mathTokenToEditorSession(token.math, equationSide);
17693
- const mode = token.display ? "display" : "inline";
17694
- if (!result.editable) {
18019
+ function openMath(token) {
18020
+ if (!editableEquations) {
18021
+ return;
18022
+ }
18023
+ openBlock(topLevelBlockIdForToken(documentRef.current, token.id));
18024
+ const result = mathTokenToEditorSession(token.math, equationSide);
18025
+ const mode = token.display ? "display" : "inline";
18026
+ if (!result.editable) {
18027
+ setSelectedMath({
18028
+ tokenId: token.id,
18029
+ fieldId: null,
18030
+ insertAt: 0,
18031
+ textTokenId: null,
18032
+ mathMode: mode,
18033
+ session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
18034
+ reason: result.reason,
18035
+ labelEnabled: Boolean(token.labelEnabled),
18036
+ label: token.label ?? ""
18037
+ });
18038
+ return;
18039
+ }
17695
18040
  setSelectedMath({
17696
18041
  tokenId: token.id,
17697
18042
  fieldId: null,
17698
18043
  insertAt: 0,
17699
18044
  textTokenId: null,
17700
18045
  mathMode: mode,
17701
- session: createEmptyEquationSession(equationSide),
17702
- reason: result.reason,
18046
+ session: equationSessionWithDocumentDigits(result.session),
18047
+ reason: null,
17703
18048
  labelEnabled: Boolean(token.labelEnabled),
17704
18049
  label: token.label ?? ""
17705
18050
  });
17706
- return;
17707
18051
  }
17708
- setSelectedMath({
17709
- tokenId: token.id,
17710
- fieldId: null,
17711
- insertAt: 0,
17712
- textTokenId: null,
17713
- mathMode: mode,
17714
- session: result.session,
17715
- reason: null,
17716
- labelEnabled: Boolean(token.labelEnabled),
17717
- label: token.label ?? ""
17718
- });
17719
- }
17720
- function toggleEditorPanel() {
17721
- setEditorOpen((open) => {
17722
- if (open && !previewOpen) {
17723
- setPreviewOpen(true);
18052
+ function toggleEditorPanel() {
18053
+ setEditorOpen((open) => {
18054
+ if (open && !previewOpen) {
18055
+ setPreviewOpen(true);
18056
+ }
18057
+ return !open;
18058
+ });
18059
+ }
18060
+ function togglePreviewPanel() {
18061
+ setPreviewOpen((open) => {
18062
+ if (open && !editorOpen) {
18063
+ setEditorOpen(true);
18064
+ }
18065
+ return !open;
18066
+ });
18067
+ }
18068
+ function saveEquation(session) {
18069
+ if (!selectedMath) {
18070
+ return;
17724
18071
  }
17725
- return !open;
17726
- });
17727
- }
17728
- function togglePreviewPanel() {
17729
- setPreviewOpen((open) => {
17730
- if (open && !editorOpen) {
17731
- setEditorOpen(true);
18072
+ const delimiters = mathDelimiters(selectedMath.mathMode);
18073
+ if (selectedMath.tokenId) {
18074
+ let next2 = replaceMathTokenFromSession(
18075
+ documentRef.current,
18076
+ selectedMath.tokenId,
18077
+ session,
18078
+ delimiters.opening,
18079
+ delimiters.closing,
18080
+ equationSide
18081
+ );
18082
+ if (selectedMath.mathMode === "display") {
18083
+ next2 = updateMathTokenLabel(next2, selectedMath.tokenId, {
18084
+ labelEnabled: selectedMath.labelEnabled,
18085
+ label: selectedMath.label
18086
+ });
18087
+ } else {
18088
+ next2 = updateMathTokenLabel(next2, selectedMath.tokenId, { labelEnabled: false, label: "" });
18089
+ }
18090
+ pendingFocusRef.current = { kind: "math", tokenId: selectedMath.tokenId };
18091
+ applyDocument(next2, "immediate");
18092
+ setSelectedMath(null);
18093
+ return;
17732
18094
  }
17733
- return !open;
17734
- });
17735
- }
17736
- function saveEquation(session) {
17737
- if (!selectedMath) {
17738
- return;
17739
- }
17740
- const delimiters = mathDelimiters(selectedMath.mathMode);
17741
- if (selectedMath.tokenId) {
17742
- let next2 = replaceMathTokenFromSession(
17743
- documentRef.current,
17744
- selectedMath.tokenId,
18095
+ let current = documentRef.current;
18096
+ let fieldId = selectedMath.fieldId;
18097
+ let textTokenId = selectedMath.textTokenId;
18098
+ let insertAt = selectedMath.insertAt;
18099
+ if (!fieldId) {
18100
+ const anchor = afterBlockId();
18101
+ current = addDocument2TextBlock(current, "\\paragraph", anchor);
18102
+ const anchorIndex = anchor ? current.blocks.findIndex((block) => block.id === anchor) : -1;
18103
+ const newIndex = anchorIndex >= 0 ? anchorIndex + 1 : current.blocks.length - 1;
18104
+ const newBlock = current.blocks[newIndex];
18105
+ const field = newBlock?.kind === "textBlock" ? newBlock.field : null;
18106
+ if (!field) {
18107
+ setSelectedMath(null);
18108
+ return;
18109
+ }
18110
+ fieldId = field.id;
18111
+ textTokenId = field.tokens.find((token) => token.kind === "text")?.id ?? null;
18112
+ insertAt = 0;
18113
+ }
18114
+ let next = insertMathTokenAtCaret(
18115
+ current,
18116
+ fieldId,
18117
+ textTokenId,
18118
+ insertAt,
17745
18119
  session,
17746
18120
  delimiters.opening,
17747
18121
  delimiters.closing,
17748
18122
  equationSide
17749
18123
  );
17750
- if (selectedMath.mathMode === "display") {
17751
- next2 = updateMathTokenLabel(next2, selectedMath.tokenId, {
17752
- labelEnabled: selectedMath.labelEnabled,
18124
+ const trailingTextTokenId = trailingTextTokenAfterInsertedMath(current, next, fieldId, textTokenId, insertAt);
18125
+ const fieldAfter = findInlineFieldById(next, fieldId);
18126
+ const insertedMathId = trailingTextTokenId && fieldAfter ? fieldAfter.tokens[Math.max(
18127
+ 0,
18128
+ fieldAfter.tokens.findIndex((token) => token.id === trailingTextTokenId) - 1
18129
+ )]?.kind === "math" ? fieldAfter.tokens[Math.max(
18130
+ 0,
18131
+ fieldAfter.tokens.findIndex((token) => token.id === trailingTextTokenId) - 1
18132
+ )]?.id : null : fieldAfter?.tokens.filter((token) => token.kind === "math").at(-1)?.id ?? null;
18133
+ if (insertedMathId && selectedMath.mathMode === "display" && selectedMath.labelEnabled) {
18134
+ next = updateMathTokenLabel(next, insertedMathId, {
18135
+ labelEnabled: true,
17753
18136
  label: selectedMath.label
17754
18137
  });
17755
- } else {
17756
- next2 = updateMathTokenLabel(next2, selectedMath.tokenId, { labelEnabled: false, label: "" });
17757
18138
  }
17758
- pendingFocusRef.current = { kind: "math", tokenId: selectedMath.tokenId };
17759
- applyDocument(next2, "immediate");
18139
+ if (trailingTextTokenId) {
18140
+ pendingFocusRef.current = { kind: "text", fieldId, textTokenId: trailingTextTokenId, caretOffset: 0 };
18141
+ }
18142
+ applyDocument(next, "immediate");
17760
18143
  setSelectedMath(null);
17761
- return;
17762
18144
  }
17763
- let current = documentRef.current;
17764
- let fieldId = selectedMath.fieldId;
17765
- let textTokenId = selectedMath.textTokenId;
17766
- let insertAt = selectedMath.insertAt;
17767
- if (!fieldId) {
17768
- const anchor = afterBlockId();
17769
- current = addDocument2TextBlock(current, "\\paragraph", anchor);
17770
- const anchorIndex = anchor ? current.blocks.findIndex((block) => block.id === anchor) : -1;
17771
- const newIndex = anchorIndex >= 0 ? anchorIndex + 1 : current.blocks.length - 1;
17772
- const newBlock = current.blocks[newIndex];
17773
- const field = newBlock?.kind === "textBlock" ? newBlock.field : null;
17774
- if (!field) {
17775
- setSelectedMath(null);
18145
+ function deleteSelectedEquation() {
18146
+ if (!selectedMath?.tokenId) {
17776
18147
  return;
17777
18148
  }
17778
- fieldId = field.id;
17779
- textTokenId = field.tokens.find((token) => token.kind === "text")?.id ?? null;
17780
- insertAt = 0;
17781
- }
17782
- let next = insertMathTokenAtCaret(
17783
- current,
17784
- fieldId,
17785
- textTokenId,
17786
- insertAt,
17787
- session,
17788
- delimiters.opening,
17789
- delimiters.closing,
17790
- equationSide
17791
- );
17792
- const trailingTextTokenId = trailingTextTokenAfterInsertedMath(current, next, fieldId, textTokenId, insertAt);
17793
- const fieldAfter = findInlineFieldById(next, fieldId);
17794
- const insertedMathId = trailingTextTokenId && fieldAfter ? fieldAfter.tokens[Math.max(
17795
- 0,
17796
- fieldAfter.tokens.findIndex((token) => token.id === trailingTextTokenId) - 1
17797
- )]?.kind === "math" ? fieldAfter.tokens[Math.max(
17798
- 0,
17799
- fieldAfter.tokens.findIndex((token) => token.id === trailingTextTokenId) - 1
17800
- )]?.id : null : fieldAfter?.tokens.filter((token) => token.kind === "math").at(-1)?.id ?? null;
17801
- if (insertedMathId && selectedMath.mathMode === "display" && selectedMath.labelEnabled) {
17802
- next = updateMathTokenLabel(next, insertedMathId, {
17803
- labelEnabled: true,
17804
- label: selectedMath.label
17805
- });
17806
- }
17807
- if (trailingTextTokenId) {
17808
- pendingFocusRef.current = { kind: "text", fieldId, textTokenId: trailingTextTokenId, caretOffset: 0 };
18149
+ const current = documentRef.current;
18150
+ const next = removeMathTokenById(current, selectedMath.tokenId);
18151
+ pendingFocusRef.current = focusAfterDeletedMath(current, next, selectedMath.tokenId);
18152
+ applyDocument(next, "immediate");
18153
+ setSelectedMath(null);
17809
18154
  }
17810
- applyDocument(next, "immediate");
17811
- setSelectedMath(null);
17812
- }
17813
- function deleteSelectedEquation() {
17814
- if (!selectedMath?.tokenId) {
17815
- return;
18155
+ function deleteMathToken(tokenId) {
18156
+ const current = documentRef.current;
18157
+ const next = removeMathTokenById(current, tokenId);
18158
+ pendingFocusRef.current = focusAfterDeletedMath(current, next, tokenId);
18159
+ applyDocument(next, "immediate");
18160
+ }
18161
+ function openCitePickerForInsert() {
18162
+ const target = resolveInsertField(documentRef.current, editorFocus);
18163
+ setCitePicker({
18164
+ tokenId: null,
18165
+ fieldId: target?.fieldId ?? null,
18166
+ textTokenId: target?.textTokenId ?? editorFocus.textTokenId,
18167
+ caretOffset: target?.caretOffset ?? editorFocus.caretOffset,
18168
+ keys: []
18169
+ });
17816
18170
  }
17817
- const current = documentRef.current;
17818
- const next = removeMathTokenById(current, selectedMath.tokenId);
17819
- pendingFocusRef.current = focusAfterDeletedMath(current, next, selectedMath.tokenId);
17820
- applyDocument(next, "immediate");
17821
- setSelectedMath(null);
17822
- }
17823
- function deleteMathToken(tokenId) {
17824
- const current = documentRef.current;
17825
- const next = removeMathTokenById(current, tokenId);
17826
- pendingFocusRef.current = focusAfterDeletedMath(current, next, tokenId);
17827
- applyDocument(next, "immediate");
17828
- }
17829
- function openCitePickerForInsert() {
17830
- const target = resolveInsertField(documentRef.current, editorFocus);
17831
- setCitePicker({
17832
- tokenId: null,
17833
- fieldId: target?.fieldId ?? null,
17834
- textTokenId: target?.textTokenId ?? editorFocus.textTokenId,
17835
- caretOffset: target?.caretOffset ?? editorFocus.caretOffset,
17836
- keys: []
17837
- });
17838
- }
17839
- function openCite(token) {
17840
- setCitePicker({
17841
- tokenId: token.id,
17842
- fieldId: null,
17843
- textTokenId: null,
17844
- caretOffset: 0,
17845
- keys: [...token.keys]
17846
- });
17847
- }
17848
- function confirmCiteKeys(keys) {
17849
- if (!citePicker || keys.length === 0) {
17850
- setCitePicker(null);
17851
- return;
18171
+ function openCite(token) {
18172
+ setCitePicker({
18173
+ tokenId: token.id,
18174
+ fieldId: null,
18175
+ textTokenId: null,
18176
+ caretOffset: 0,
18177
+ keys: [...token.keys]
18178
+ });
17852
18179
  }
17853
- if (citePicker.tokenId) {
17854
- applyDocument(updateCiteTokenKeys(documentRef.current, citePicker.tokenId, keys), "immediate");
17855
- pendingFocusRef.current = { kind: "cite", tokenId: citePicker.tokenId };
18180
+ function confirmCiteKeys(keys) {
18181
+ if (!citePicker || keys.length === 0) {
18182
+ setCitePicker(null);
18183
+ return;
18184
+ }
18185
+ if (citePicker.tokenId) {
18186
+ applyDocument(updateCiteTokenKeys(documentRef.current, citePicker.tokenId, keys), "immediate");
18187
+ pendingFocusRef.current = { kind: "cite", tokenId: citePicker.tokenId };
18188
+ setCitePicker(null);
18189
+ return;
18190
+ }
18191
+ const target = resolveInsertField(documentRef.current, editorFocus);
18192
+ const fieldId = citePicker.fieldId ?? target?.fieldId;
18193
+ if (!fieldId) {
18194
+ setCitePicker(null);
18195
+ return;
18196
+ }
18197
+ const textTokenId = citePicker.textTokenId ?? target?.textTokenId ?? null;
18198
+ const caretOffset = citePicker.caretOffset ?? target?.caretOffset ?? 0;
18199
+ const next = insertCiteTokenAtCaret(documentRef.current, fieldId, textTokenId, caretOffset, keys);
18200
+ applyDocument(next, "immediate");
17856
18201
  setCitePicker(null);
17857
- return;
17858
18202
  }
17859
- const target = resolveInsertField(documentRef.current, editorFocus);
17860
- const fieldId = citePicker.fieldId ?? target?.fieldId;
17861
- if (!fieldId) {
17862
- setCitePicker(null);
17863
- return;
18203
+ function deleteCiteToken(tokenId) {
18204
+ applyDocument(removeCiteTokenById(documentRef.current, tokenId), "immediate");
18205
+ }
18206
+ function openRefPickerForInsert() {
18207
+ const target = resolveInsertField(documentRef.current, editorFocus);
18208
+ setRefPicker({
18209
+ tokenId: null,
18210
+ fieldId: target?.fieldId ?? null,
18211
+ textTokenId: target?.textTokenId ?? editorFocus.textTokenId,
18212
+ caretOffset: target?.caretOffset ?? editorFocus.caretOffset,
18213
+ keys: [],
18214
+ refCommand: "ref"
18215
+ });
17864
18216
  }
17865
- const textTokenId = citePicker.textTokenId ?? target?.textTokenId ?? null;
17866
- const caretOffset = citePicker.caretOffset ?? target?.caretOffset ?? 0;
17867
- const next = insertCiteTokenAtCaret(documentRef.current, fieldId, textTokenId, caretOffset, keys);
17868
- applyDocument(next, "immediate");
17869
- setCitePicker(null);
17870
- }
17871
- function deleteCiteToken(tokenId) {
17872
- applyDocument(removeCiteTokenById(documentRef.current, tokenId), "immediate");
17873
- }
17874
- function openRefPickerForInsert() {
17875
- const target = resolveInsertField(documentRef.current, editorFocus);
17876
- setRefPicker({
17877
- tokenId: null,
17878
- fieldId: target?.fieldId ?? null,
17879
- textTokenId: target?.textTokenId ?? editorFocus.textTokenId,
17880
- caretOffset: target?.caretOffset ?? editorFocus.caretOffset,
17881
- keys: [],
17882
- refCommand: "ref"
17883
- });
17884
- }
17885
- function openRef(token) {
17886
- setRefPicker({
17887
- tokenId: token.id,
17888
- fieldId: null,
17889
- textTokenId: null,
17890
- caretOffset: 0,
17891
- keys: [...token.keys],
17892
- refCommand: token.refCommand
17893
- });
17894
- }
17895
- function confirmRefKeys(keys, refCommand) {
17896
- if (!refPicker || keys.length === 0) {
17897
- setRefPicker(null);
17898
- return;
18217
+ function openRef(token) {
18218
+ setRefPicker({
18219
+ tokenId: token.id,
18220
+ fieldId: null,
18221
+ textTokenId: null,
18222
+ caretOffset: 0,
18223
+ keys: [...token.keys],
18224
+ refCommand: token.refCommand
18225
+ });
17899
18226
  }
17900
- if (refPicker.tokenId) {
17901
- applyDocument(updateRefTokenKeys(documentRef.current, refPicker.tokenId, keys, refCommand), "immediate");
17902
- pendingFocusRef.current = { kind: "ref", tokenId: refPicker.tokenId };
18227
+ function confirmRefKeys(keys, refCommand) {
18228
+ if (!refPicker || keys.length === 0) {
18229
+ setRefPicker(null);
18230
+ return;
18231
+ }
18232
+ if (refPicker.tokenId) {
18233
+ applyDocument(updateRefTokenKeys(documentRef.current, refPicker.tokenId, keys, refCommand), "immediate");
18234
+ pendingFocusRef.current = { kind: "ref", tokenId: refPicker.tokenId };
18235
+ setRefPicker(null);
18236
+ return;
18237
+ }
18238
+ const target = resolveInsertField(documentRef.current, editorFocus);
18239
+ const fieldId = refPicker.fieldId ?? target?.fieldId;
18240
+ if (!fieldId) {
18241
+ setRefPicker(null);
18242
+ return;
18243
+ }
18244
+ const textTokenId = refPicker.textTokenId ?? target?.textTokenId ?? null;
18245
+ const caretOffset = refPicker.caretOffset ?? target?.caretOffset ?? 0;
18246
+ const next = insertRefTokenAtCaret(documentRef.current, fieldId, textTokenId, caretOffset, keys, refCommand);
18247
+ applyDocument(next, "immediate");
17903
18248
  setRefPicker(null);
17904
- return;
17905
18249
  }
17906
- const target = resolveInsertField(documentRef.current, editorFocus);
17907
- const fieldId = refPicker.fieldId ?? target?.fieldId;
17908
- if (!fieldId) {
17909
- setRefPicker(null);
17910
- return;
18250
+ function deleteRefToken(tokenId) {
18251
+ applyDocument(removeRefTokenById(documentRef.current, tokenId), "immediate");
17911
18252
  }
17912
- const textTokenId = refPicker.textTokenId ?? target?.textTokenId ?? null;
17913
- const caretOffset = refPicker.caretOffset ?? target?.caretOffset ?? 0;
17914
- const next = insertRefTokenAtCaret(documentRef.current, fieldId, textTokenId, caretOffset, keys, refCommand);
17915
- applyDocument(next, "immediate");
17916
- setRefPicker(null);
17917
- }
17918
- function deleteRefToken(tokenId) {
17919
- applyDocument(removeRefTokenById(documentRef.current, tokenId), "immediate");
17920
- }
17921
- function toggleInlineTextStyle(styleName) {
17922
- if (!canFormatText || !editorFocus.fieldId || !editorFocus.textTokenId) {
17923
- return;
18253
+ function toggleInlineTextStyle(styleName) {
18254
+ if (!canFormatText || !editorFocus.fieldId || !editorFocus.textTokenId) {
18255
+ return;
18256
+ }
18257
+ applyDocument(
18258
+ toggleTextTokenStyle(
18259
+ documentRef.current,
18260
+ editorFocus.fieldId,
18261
+ editorFocus.textTokenId,
18262
+ editorFocus.selectionStart,
18263
+ editorFocus.selectionEnd,
18264
+ styleName
18265
+ ),
18266
+ "immediate"
18267
+ );
17924
18268
  }
17925
- applyDocument(
17926
- toggleTextTokenStyle(
17927
- documentRef.current,
17928
- editorFocus.fieldId,
17929
- editorFocus.textTokenId,
17930
- editorFocus.selectionStart,
17931
- editorFocus.selectionEnd,
17932
- styleName
17933
- ),
17934
- "immediate"
17935
- );
17936
- }
17937
- const showEditorPanel = !previewOnly && editorOpen;
17938
- const showPreviewPanel = previewOnly || previewOpen;
17939
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
17940
- "div",
17941
- {
17942
- ref: widgetRef,
17943
- className: ["butex-document2-widget", className].filter(Boolean).join(" "),
17944
- dir: uiLocaleDirection(uiLocale),
17945
- lang: uiLocale,
17946
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__shell", children: [
17947
- !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__toolbar", children: [
17948
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
17949
- DocumentInsertToolbar,
17950
- {
17951
- canUndo,
17952
- canRedo,
17953
- editableEquations,
17954
- uiLocale,
17955
- digitForm,
17956
- selectionCount,
17957
- canMoveSelectionUp,
17958
- canMoveSelectionDown,
17959
- canFormatText,
17960
- activeTextStyles,
17961
- onUndo: undoDocument,
17962
- onRedo: redoDocument,
17963
- onToggleTextStyle: toggleInlineTextStyle,
17964
- onMoveSelectionUp: () => moveSelectedBlocks(-1),
17965
- onMoveSelectionDown: () => moveSelectedBlocks(1),
17966
- onDeleteSelection: deleteSelectedBlocks,
17967
- onAddSection: () => {
17968
- clearBlockSelection();
17969
- applyDocument(addDocument2TextBlock(documentRef.current, "\\section", afterBlockId()), "immediate");
17970
- },
17971
- onAddSubsection: () => {
17972
- clearBlockSelection();
17973
- applyDocument(addDocument2TextBlock(documentRef.current, "\\subsection", afterBlockId()), "immediate");
17974
- },
17975
- onAddSubsubsection: () => {
17976
- clearBlockSelection();
17977
- applyDocument(addDocument2TextBlock(documentRef.current, "\\subsubsection", afterBlockId()), "immediate");
17978
- },
17979
- onAddParagraph: () => {
17980
- clearBlockSelection();
17981
- applyDocument(addDocument2TextBlock(documentRef.current, "\\paragraph", afterBlockId()), "immediate");
17982
- },
17983
- onAddInlineEquation: () => openNewEquation("inline"),
17984
- onAddDisplayEquation: () => openNewEquation("display"),
17985
- onAddTable: (rowCount, colCount) => {
17986
- clearBlockSelection();
17987
- applyDocument(addDocument2TableBlock(documentRef.current, "l".repeat(colCount), rowCount, colCount, afterBlockId()), "immediate");
17988
- },
17989
- onAddList: () => {
17990
- clearBlockSelection();
17991
- applyDocument(addDocument2ListBlock(documentRef.current, false, afterBlockId()), "immediate");
17992
- },
17993
- onAddEnumerate: () => {
17994
- clearBlockSelection();
17995
- applyDocument(addDocument2ListBlock(documentRef.current, true, afterBlockId()), "immediate");
17996
- },
17997
- onAddFigure: () => {
17998
- clearBlockSelection();
17999
- applyDocument(addDocument2ImageBlock(documentRef.current, "", afterBlockId()), "immediate");
18000
- },
18001
- onInsertCitation: openCitePickerForInsert,
18002
- onInsertInternalRef: openRefPickerForInsert,
18003
- onInsertBibliography: () => {
18004
- clearBlockSelection();
18005
- applyDocument(ensureDocument2BibliographyBlock(documentRef.current, afterBlockId()), "immediate");
18006
- },
18007
- onManageReferences: () => setReferencesOpen(true),
18008
- onManageLabels: () => setLabelsOpen(true),
18009
- onOpenArticleMeta: () => focusArticleMetaPanel(articleMetaPanelRef.current),
18010
- onDigitFormChange: (next) => {
18011
- setDigitFormState(next);
18012
- onDigitFormChange?.(next);
18269
+ const showEditorPanel = !previewOnly && editorOpen;
18270
+ const showPreviewPanel = previewOnly || previewOpen;
18271
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18272
+ "div",
18273
+ {
18274
+ ref: widgetRef,
18275
+ className: ["butex-document2-widget", className].filter(Boolean).join(" "),
18276
+ dir: uiLocaleDirection(uiLocale),
18277
+ lang: uiLocale,
18278
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__shell", children: [
18279
+ !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__toolbar", children: [
18280
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18281
+ DocumentInsertToolbar,
18282
+ {
18283
+ canUndo,
18284
+ canRedo,
18285
+ editableEquations,
18286
+ uiLocale,
18287
+ digitForm,
18288
+ selectionCount,
18289
+ canMoveSelectionUp,
18290
+ canMoveSelectionDown,
18291
+ canFormatText,
18292
+ activeTextStyles,
18293
+ onUndo: undoDocument,
18294
+ onRedo: redoDocument,
18295
+ onToggleTextStyle: toggleInlineTextStyle,
18296
+ onMoveSelectionUp: () => moveSelectedBlocks(-1),
18297
+ onMoveSelectionDown: () => moveSelectedBlocks(1),
18298
+ onDeleteSelection: deleteSelectedBlocks,
18299
+ onAddSection: () => {
18300
+ clearBlockSelection();
18301
+ applyDocument(addDocument2TextBlock(documentRef.current, "\\section", afterBlockId()), "immediate");
18302
+ },
18303
+ onAddSubsection: () => {
18304
+ clearBlockSelection();
18305
+ applyDocument(addDocument2TextBlock(documentRef.current, "\\subsection", afterBlockId()), "immediate");
18306
+ },
18307
+ onAddSubsubsection: () => {
18308
+ clearBlockSelection();
18309
+ applyDocument(addDocument2TextBlock(documentRef.current, "\\subsubsection", afterBlockId()), "immediate");
18310
+ },
18311
+ onAddParagraph: () => {
18312
+ clearBlockSelection();
18313
+ applyDocument(addDocument2TextBlock(documentRef.current, "\\paragraph", afterBlockId()), "immediate");
18314
+ },
18315
+ onAddInlineEquation: () => openNewEquation("inline"),
18316
+ onAddDisplayEquation: () => openNewEquation("display"),
18317
+ onAddTable: (rowCount, colCount) => {
18318
+ clearBlockSelection();
18319
+ applyDocument(addDocument2TableBlock(documentRef.current, "l".repeat(colCount), rowCount, colCount, afterBlockId()), "immediate");
18320
+ },
18321
+ onAddList: () => {
18322
+ clearBlockSelection();
18323
+ applyDocument(addDocument2ListBlock(documentRef.current, false, afterBlockId()), "immediate");
18324
+ },
18325
+ onAddEnumerate: () => {
18326
+ clearBlockSelection();
18327
+ applyDocument(addDocument2ListBlock(documentRef.current, true, afterBlockId()), "immediate");
18328
+ },
18329
+ onAddFigure: () => insertImageBlock(""),
18330
+ onInsertCitation: openCitePickerForInsert,
18331
+ onInsertInternalRef: openRefPickerForInsert,
18332
+ onInsertBibliography: () => {
18333
+ clearBlockSelection();
18334
+ applyDocument(ensureDocument2BibliographyBlock(documentRef.current, afterBlockId()), "immediate");
18335
+ },
18336
+ onManageReferences: () => setReferencesOpen(true),
18337
+ onManageLabels: () => setLabelsOpen(true),
18338
+ onOpenArticleMeta: () => focusArticleMetaPanel(articleMetaPanelRef.current),
18339
+ onDigitFormChange: (next) => {
18340
+ setDigitFormState(next);
18341
+ onDigitFormChange?.(next);
18342
+ }
18013
18343
  }
18014
- }
18015
- ),
18016
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.panels, children: [
18017
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", "aria-pressed": editorOpen, onClick: toggleEditorPanel, children: editorOpen ? messages.hideEditor : messages.editor }),
18018
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", "aria-pressed": previewOpen, onClick: togglePreviewPanel, children: previewOpen ? messages.hidePreview : messages.preview })
18019
- ] }),
18020
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.collapseBlocks, children: [
18021
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: collapseAllBlocks, children: messages.collapseAll }),
18022
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: openAllBlocks, children: messages.openAll })
18023
- ] })
18024
- ] }) : null,
18025
- error ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "butex-document2-widget__error", children: error }) : null,
18026
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
18027
- "div",
18028
- {
18029
- className: `butex-document2-widget__layout butex-document2-widget__layout--editor-${showEditorPanel ? "open" : "closed"} butex-document2-widget__layout--preview-${showPreviewPanel ? "open" : "closed"}`,
18030
- children: [
18031
- !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18032
- "section",
18033
- {
18034
- className: "butex-document2-widget__panel butex-document2-widget__editor-panel",
18035
- "aria-label": messages.documentEditor,
18036
- "aria-hidden": !showEditorPanel,
18037
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__blocks", children: [
18038
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18039
- ArticleMetaPanel,
18040
- {
18041
- meta: documentNode.meta ?? emptyDocument2Meta(),
18042
- uiLocale,
18043
- digitForm,
18044
- panelRef: articleMetaPanelRef,
18045
- onChange: (patch) => {
18046
- clearBlockSelection();
18047
- applyDocument(updateDocument2Meta(documentRef.current, patch), "text");
18344
+ ),
18345
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.panels, children: [
18346
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", "aria-pressed": editorOpen, onClick: toggleEditorPanel, children: editorOpen ? messages.hideEditor : messages.editor }),
18347
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", "aria-pressed": previewOpen, onClick: togglePreviewPanel, children: previewOpen ? messages.hidePreview : messages.preview })
18348
+ ] }),
18349
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.collapseBlocks, children: [
18350
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: collapseAllBlocks, children: messages.collapseAll }),
18351
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: openAllBlocks, children: messages.openAll })
18352
+ ] })
18353
+ ] }) : null,
18354
+ error ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "butex-document2-widget__error", children: error }) : null,
18355
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
18356
+ "div",
18357
+ {
18358
+ className: `butex-document2-widget__layout butex-document2-widget__layout--editor-${showEditorPanel ? "open" : "closed"} butex-document2-widget__layout--preview-${showPreviewPanel ? "open" : "closed"}`,
18359
+ children: [
18360
+ !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18361
+ "section",
18362
+ {
18363
+ className: "butex-document2-widget__panel butex-document2-widget__editor-panel",
18364
+ "aria-label": messages.documentEditor,
18365
+ "aria-hidden": !showEditorPanel,
18366
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__blocks", children: [
18367
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18368
+ ArticleMetaPanel,
18369
+ {
18370
+ meta: documentNode.meta ?? emptyDocument2Meta(),
18371
+ uiLocale,
18372
+ digitForm,
18373
+ panelRef: articleMetaPanelRef,
18374
+ onChange: (patch) => {
18375
+ clearBlockSelection();
18376
+ applyDocument(updateDocument2Meta(documentRef.current, patch), "text");
18377
+ }
18048
18378
  }
18049
- }
18050
- ),
18051
- documentNode.blocks.map((block, blockIndex) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18052
- BlockEditor,
18379
+ ),
18380
+ documentNode.blocks.map((block, blockIndex) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18381
+ BlockEditor,
18382
+ {
18383
+ block,
18384
+ references: documentNode.references,
18385
+ documentNode,
18386
+ documentDirection,
18387
+ digitForm,
18388
+ mathOutput,
18389
+ equationSide,
18390
+ editableEquations,
18391
+ editableCitations: !previewOnly,
18392
+ uiLocale,
18393
+ isCollapsed: collapsedBlockIds.has(block.id),
18394
+ selected: Boolean(blockSelection && blockIndex >= blockSelection.from && blockIndex <= blockSelection.to),
18395
+ onToggleSelect: toggleSelectBlock,
18396
+ onTextChange: (fieldId, tokenId, text) => {
18397
+ clearBlockSelection();
18398
+ applyDocument(updateTextToken(documentRef.current, fieldId, tokenId, text), "text");
18399
+ },
18400
+ onOpenMath: openMath,
18401
+ onDeleteMath: editableEquations ? deleteMathToken : void 0,
18402
+ onOpenCite: openCite,
18403
+ onDeleteCite: deleteCiteToken,
18404
+ onOpenRef: openRef,
18405
+ onDeleteRef: deleteRefToken,
18406
+ onToggleCollapse: toggleBlockCollapse,
18407
+ onBlockFocus: rememberBlockFocus,
18408
+ onFieldFocus: rememberFieldFocus,
18409
+ onMathFocus: rememberMathFocus,
18410
+ onFieldBlur,
18411
+ onImageSrcChange: (blockId, value) => {
18412
+ clearBlockSelection();
18413
+ applyDocument(updateDocument2ImageValue(documentRef.current, blockId, value), "text");
18414
+ },
18415
+ onFloatMetaChange: (blockId, kind, patch) => {
18416
+ clearBlockSelection();
18417
+ applyDocument(
18418
+ kind === "image" ? updateDocument2ImageMeta(documentRef.current, blockId, patch) : updateDocument2TableMeta(documentRef.current, blockId, patch),
18419
+ "text"
18420
+ );
18421
+ },
18422
+ onParagraphCenteredChange: (blockId, centered) => {
18423
+ clearBlockSelection();
18424
+ applyDocument(updateDocument2TextBlockCentered(documentRef.current, blockId, centered), "text");
18425
+ },
18426
+ onAddListItem: (listBlockId) => {
18427
+ clearBlockSelection();
18428
+ applyDocument(addDocument2ListItem(documentRef.current, listBlockId), "immediate");
18429
+ },
18430
+ onRemoveListItem: (listBlockId, itemId) => {
18431
+ clearBlockSelection();
18432
+ applyDocument(removeDocument2ListItem(documentRef.current, listBlockId, itemId), "immediate");
18433
+ },
18434
+ onManageReferences: () => setReferencesOpen(true)
18435
+ },
18436
+ block.id
18437
+ ))
18438
+ ] })
18439
+ }
18440
+ ) : null,
18441
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18442
+ "section",
18443
+ {
18444
+ className: "butex-document2-widget__panel butex-document2-widget__preview-panel",
18445
+ "aria-label": messages.documentPreview,
18446
+ "aria-hidden": !showPreviewPanel,
18447
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18448
+ DocumentPreview,
18053
18449
  {
18054
- block,
18055
- references: documentNode.references,
18056
- documentNode,
18450
+ blocks: preview.blocks,
18451
+ output: mathOutput,
18057
18452
  documentDirection,
18058
- digitForm,
18059
- mathOutput,
18060
- equationSide,
18061
- editableEquations,
18062
- editableCitations: !previewOnly,
18063
18453
  uiLocale,
18064
- isCollapsed: collapsedBlockIds.has(block.id),
18065
- selected: Boolean(blockSelection && blockIndex >= blockSelection.from && blockIndex <= blockSelection.to),
18066
- onToggleSelect: toggleSelectBlock,
18067
- onTextChange: (fieldId, tokenId, text) => {
18068
- clearBlockSelection();
18069
- applyDocument(updateTextToken(documentRef.current, fieldId, tokenId, text), "text");
18070
- },
18071
- onOpenMath: openMath,
18072
- onDeleteMath: editableEquations ? deleteMathToken : void 0,
18073
- onOpenCite: openCite,
18074
- onDeleteCite: deleteCiteToken,
18075
- onOpenRef: openRef,
18076
- onDeleteRef: deleteRefToken,
18077
- onToggleCollapse: toggleBlockCollapse,
18078
- onBlockFocus: rememberBlockFocus,
18079
- onFieldFocus: rememberFieldFocus,
18080
- onMathFocus: rememberMathFocus,
18081
- onFieldBlur,
18082
- onImageSrcChange: (blockId, value) => {
18083
- clearBlockSelection();
18084
- applyDocument(updateDocument2ImageValue(documentRef.current, blockId, value), "text");
18085
- },
18086
- onFloatMetaChange: (blockId, kind, patch) => {
18087
- clearBlockSelection();
18088
- applyDocument(
18089
- kind === "image" ? updateDocument2ImageMeta(documentRef.current, blockId, patch) : updateDocument2TableMeta(documentRef.current, blockId, patch),
18090
- "text"
18091
- );
18092
- },
18093
- onParagraphCenteredChange: (blockId, centered) => {
18094
- clearBlockSelection();
18095
- applyDocument(updateDocument2TextBlockCentered(documentRef.current, blockId, centered), "text");
18096
- },
18097
- onAddListItem: (listBlockId) => {
18098
- clearBlockSelection();
18099
- applyDocument(addDocument2ListItem(documentRef.current, listBlockId), "immediate");
18100
- },
18101
- onRemoveListItem: (listBlockId, itemId) => {
18102
- clearBlockSelection();
18103
- applyDocument(removeDocument2ListItem(documentRef.current, listBlockId, itemId), "immediate");
18104
- },
18105
- onManageReferences: () => setReferencesOpen(true)
18106
- },
18107
- block.id
18108
- ))
18109
- ] })
18110
- }
18111
- ) : null,
18454
+ digitForm,
18455
+ resolveImageUrl
18456
+ }
18457
+ )
18458
+ }
18459
+ )
18460
+ ]
18461
+ }
18462
+ ),
18463
+ debugEnabled ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__dev", children: [
18464
+ debugEnabled && documentNode.diagnostics.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
18465
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: messages.importWarnings }),
18466
+ 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}`))
18467
+ ] }) : null,
18468
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__dev-actions", children: [
18469
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: () => void copyDebugText(JSON.stringify(documentJson, null, 2)), children: "Copy JSON" }),
18470
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: () => void copyDebugText(latex), children: "Copy TeX" }),
18471
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", "aria-expanded": debugImportOpen, onClick: openDebugJsonImport, children: "Import JSON" })
18472
+ ] }),
18473
+ debugImportOpen ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__dev-import", children: [
18112
18474
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18113
- "section",
18475
+ "textarea",
18114
18476
  {
18115
- className: "butex-document2-widget__panel butex-document2-widget__preview-panel",
18116
- "aria-label": messages.documentPreview,
18117
- "aria-hidden": !showPreviewPanel,
18118
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18119
- DocumentPreview,
18120
- {
18121
- blocks: preview.blocks,
18122
- output: mathOutput,
18123
- documentDirection,
18124
- uiLocale,
18125
- digitForm,
18126
- resolveImageUrl
18127
- }
18128
- )
18477
+ value: debugImportText,
18478
+ "aria-label": "Import Document2 JSON",
18479
+ spellCheck: false,
18480
+ onChange: (event) => {
18481
+ setDebugImportText(event.currentTarget.value);
18482
+ setDebugImportError("");
18483
+ }
18129
18484
  }
18130
- )
18131
- ]
18132
- }
18133
- ),
18134
- debugEnabled ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__dev", children: [
18135
- debugEnabled && documentNode.diagnostics.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
18136
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: messages.importWarnings }),
18137
- 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}`))
18485
+ ),
18486
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "butex-document2-widget__dev-actions", children: [
18487
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: applyDebugJsonImport, children: "Apply" }),
18488
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18489
+ "button",
18490
+ {
18491
+ type: "button",
18492
+ onClick: () => {
18493
+ setDebugImportOpen(false);
18494
+ setDebugImportError("");
18495
+ },
18496
+ children: "Cancel"
18497
+ }
18498
+ )
18499
+ ] }),
18500
+ debugImportError ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "butex-document2-widget__dev-error", children: debugImportError }) : null
18501
+ ] }) : null,
18502
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "LaTeX" }),
18503
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pre", { children: latex }),
18504
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "JSON" }),
18505
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pre", { children: JSON.stringify(documentJson, null, 2) }),
18506
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "AST" }),
18507
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pre", { children: JSON.stringify(documentNode, null, 2) })
18138
18508
  ] }) : null,
18139
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "LaTeX" }),
18140
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pre", { children: latex }),
18141
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "AST" }),
18142
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pre", { children: JSON.stringify(documentNode, null, 2) })
18143
- ] }) : null,
18144
- !previewOnly && selectedMath ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18145
- EquationDrawer,
18146
- {
18147
- session: selectedMath.session,
18148
- reason: selectedMath.reason,
18149
- mathMode: selectedMath.mathMode,
18150
- canDelete: Boolean(selectedMath.tokenId),
18151
- equationSide,
18152
- uiLocale,
18153
- labelEnabled: selectedMath.labelEnabled,
18154
- label: selectedMath.label,
18155
- labels: documentLabels,
18156
- references: documentNode.references,
18157
- ownerId: selectedMath.tokenId ?? void 0,
18158
- onLabelEnabledChange: (enabled) => setSelectedMath((current) => current ? { ...current, labelEnabled: enabled } : current),
18159
- onLabelChange: (nextLabel) => setSelectedMath((current) => current ? { ...current, label: nextLabel } : current),
18160
- onMathModeChange: (mode) => setSelectedMath((current) => current ? { ...current, mathMode: mode } : current),
18161
- onClose: () => setSelectedMath(null),
18162
- onSave: saveEquation,
18163
- onDelete: deleteSelectedEquation
18164
- }
18165
- ) : null,
18166
- !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18167
- CitePickerPopover,
18168
- {
18169
- open: citePicker !== null,
18170
- references: documentNode.references,
18171
- initialKeys: citePicker?.keys ?? [],
18172
- uiLocale,
18173
- digitForm,
18174
- onClose: () => setCitePicker(null),
18175
- onConfirm: confirmCiteKeys,
18176
- onManageReferences: () => {
18177
- setCitePicker(null);
18178
- setReferencesOpen(true);
18509
+ !previewOnly && selectedMath ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18510
+ EquationDrawer,
18511
+ {
18512
+ debug: debugEnabled,
18513
+ session: selectedMath.session,
18514
+ reason: selectedMath.reason,
18515
+ mathMode: selectedMath.mathMode,
18516
+ canDelete: Boolean(selectedMath.tokenId),
18517
+ equationSide,
18518
+ uiLocale,
18519
+ labelEnabled: selectedMath.labelEnabled,
18520
+ label: selectedMath.label,
18521
+ labels: documentLabels,
18522
+ references: documentNode.references,
18523
+ ownerId: selectedMath.tokenId ?? void 0,
18524
+ onLabelEnabledChange: (enabled) => setSelectedMath((current) => current ? { ...current, labelEnabled: enabled } : current),
18525
+ onLabelChange: (nextLabel) => setSelectedMath((current) => current ? { ...current, label: nextLabel } : current),
18526
+ onMathModeChange: (mode) => setSelectedMath((current) => current ? { ...current, mathMode: mode } : current),
18527
+ onClose: () => setSelectedMath(null),
18528
+ onSave: saveEquation,
18529
+ onDelete: deleteSelectedEquation
18179
18530
  }
18180
- }
18181
- ) : null,
18182
- !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18183
- RefPickerPopover,
18184
- {
18185
- open: refPicker !== null,
18186
- labels: documentLabels,
18187
- initialKeys: refPicker?.keys ?? [],
18188
- initialRefCommand: refPicker?.refCommand ?? "ref",
18189
- uiLocale,
18190
- digitForm,
18191
- onClose: () => setRefPicker(null),
18192
- onConfirm: confirmRefKeys,
18193
- onManageLabels: () => {
18194
- setRefPicker(null);
18195
- setLabelsOpen(true);
18531
+ ) : null,
18532
+ !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18533
+ CitePickerPopover,
18534
+ {
18535
+ open: citePicker !== null,
18536
+ references: documentNode.references,
18537
+ initialKeys: citePicker?.keys ?? [],
18538
+ uiLocale,
18539
+ digitForm,
18540
+ onClose: () => setCitePicker(null),
18541
+ onConfirm: confirmCiteKeys,
18542
+ onManageReferences: () => {
18543
+ setCitePicker(null);
18544
+ setReferencesOpen(true);
18545
+ }
18196
18546
  }
18197
- }
18198
- ) : null,
18199
- !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18200
- ReferencesPanel,
18201
- {
18202
- open: referencesOpen,
18203
- references: documentNode.references,
18204
- labels: documentLabels,
18205
- uiLocale,
18206
- digitForm,
18207
- onClose: () => setReferencesOpen(false),
18208
- onAdd: (partial) => applyDocument(addDocument2Reference(documentRef.current, partial), "immediate"),
18209
- onUpdate: (referenceId, patch) => applyDocument(updateDocument2Reference(documentRef.current, referenceId, patch), "immediate"),
18210
- onRemove: (referenceId) => applyDocument(removeDocument2Reference(documentRef.current, referenceId), "immediate"),
18211
- onMove: (referenceId, direction) => applyDocument(moveDocument2Reference(documentRef.current, referenceId, direction), "immediate")
18212
- }
18213
- ) : null,
18214
- !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18215
- LabelsPanel,
18216
- {
18217
- open: labelsOpen,
18218
- labels: documentLabels,
18219
- references: documentNode.references,
18220
- uiLocale,
18221
- digitForm,
18222
- onClose: () => setLabelsOpen(false),
18223
- onUpdateFloat: (ownerId, kind, patch) => applyDocument(
18224
- kind === "fig" ? updateDocument2ImageMeta(documentRef.current, ownerId, patch) : updateDocument2TableMeta(documentRef.current, ownerId, patch),
18225
- "text"
18226
- ),
18227
- onUpdateEquationLabel: (tokenId, patch) => applyDocument(updateMathTokenLabel(documentRef.current, tokenId, patch), "text")
18228
- }
18229
- ) : null
18230
- ] })
18231
- }
18232
- );
18233
- }
18547
+ ) : null,
18548
+ !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18549
+ RefPickerPopover,
18550
+ {
18551
+ open: refPicker !== null,
18552
+ labels: documentLabels,
18553
+ initialKeys: refPicker?.keys ?? [],
18554
+ initialRefCommand: refPicker?.refCommand ?? "ref",
18555
+ uiLocale,
18556
+ digitForm,
18557
+ onClose: () => setRefPicker(null),
18558
+ onConfirm: confirmRefKeys,
18559
+ onManageLabels: () => {
18560
+ setRefPicker(null);
18561
+ setLabelsOpen(true);
18562
+ }
18563
+ }
18564
+ ) : null,
18565
+ !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18566
+ ReferencesPanel,
18567
+ {
18568
+ open: referencesOpen,
18569
+ references: documentNode.references,
18570
+ labels: documentLabels,
18571
+ uiLocale,
18572
+ digitForm,
18573
+ onClose: () => setReferencesOpen(false),
18574
+ onAdd: (partial) => applyDocument(addDocument2Reference(documentRef.current, partial), "immediate"),
18575
+ onUpdate: (referenceId, patch) => applyDocument(updateDocument2Reference(documentRef.current, referenceId, patch), "immediate"),
18576
+ onRemove: (referenceId) => applyDocument(removeDocument2Reference(documentRef.current, referenceId), "immediate"),
18577
+ onMove: (referenceId, direction) => applyDocument(moveDocument2Reference(documentRef.current, referenceId, direction), "immediate")
18578
+ }
18579
+ ) : null,
18580
+ !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
18581
+ LabelsPanel,
18582
+ {
18583
+ open: labelsOpen,
18584
+ labels: documentLabels,
18585
+ references: documentNode.references,
18586
+ uiLocale,
18587
+ digitForm,
18588
+ onClose: () => setLabelsOpen(false),
18589
+ onUpdateFloat: (ownerId, kind, patch) => applyDocument(
18590
+ kind === "fig" ? updateDocument2ImageMeta(documentRef.current, ownerId, patch) : updateDocument2TableMeta(documentRef.current, ownerId, patch),
18591
+ "text"
18592
+ ),
18593
+ onUpdateEquationLabel: (tokenId, patch) => applyDocument(updateMathTokenLabel(documentRef.current, tokenId, patch), "text")
18594
+ }
18595
+ ) : null
18596
+ ] })
18597
+ }
18598
+ );
18599
+ }
18600
+ );
18601
+ ButexDocumentEditor2.displayName = "ButexDocumentEditor2";
18234
18602
  // Annotate the CommonJS export names for ESM import in node:
18235
18603
  0 && (module.exports = {
18236
18604
  ButexDocumentEditor2,