@drghaliasri/butex 5.3.2 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1353,6 +1353,155 @@ function createEmptyDocument2() {
1353
1353
  };
1354
1354
  }
1355
1355
 
1356
+ // src/editor/accentCommands.ts
1357
+ var ACCENT_COMMANDS = {
1358
+ vec: {
1359
+ id: "vec",
1360
+ englishTex: "\\vec",
1361
+ arabicTex: "\\arabvec",
1362
+ placement: "over",
1363
+ label: "\u20D7",
1364
+ title: "\u0633\u0647\u0645 \u0641\u0648\u0642"
1365
+ },
1366
+ hat: {
1367
+ id: "hat",
1368
+ englishTex: "\\hat",
1369
+ arabicTex: "\\hat",
1370
+ placement: "over",
1371
+ label: "\u02C6",
1372
+ title: "\u0642\u0628\u0639\u0629"
1373
+ },
1374
+ tilde: {
1375
+ id: "tilde",
1376
+ englishTex: "\\tilde",
1377
+ arabicTex: "\\tilde",
1378
+ placement: "over",
1379
+ label: "\u02DC",
1380
+ title: "\u0645\u062F\u0629"
1381
+ },
1382
+ dot: {
1383
+ id: "dot",
1384
+ englishTex: "\\dot",
1385
+ arabicTex: "\\dot",
1386
+ placement: "over",
1387
+ label: "\u02D9",
1388
+ title: "\u0646\u0642\u0637\u0629 \u0641\u0648\u0642"
1389
+ },
1390
+ ddot: {
1391
+ id: "ddot",
1392
+ englishTex: "\\ddot",
1393
+ arabicTex: "\\ddot",
1394
+ placement: "over",
1395
+ label: "\xA8",
1396
+ title: "\u0646\u0642\u0637\u062A\u0627\u0646 \u0641\u0648\u0642"
1397
+ },
1398
+ dddot: {
1399
+ id: "dddot",
1400
+ englishTex: "\\dddot",
1401
+ arabicTex: "\\dddot",
1402
+ placement: "over",
1403
+ label: "\u20DB",
1404
+ title: "\u062B\u0644\u0627\u062B \u0646\u0642\u0627\u0637 \u0641\u0648\u0642"
1405
+ },
1406
+ bar: {
1407
+ id: "bar",
1408
+ englishTex: "\\bar",
1409
+ arabicTex: "\\bar",
1410
+ placement: "over",
1411
+ label: "\xAF",
1412
+ title: "\u062E\u0637 \u0641\u0648\u0642"
1413
+ },
1414
+ check: {
1415
+ id: "check",
1416
+ englishTex: "\\check",
1417
+ arabicTex: "\\check",
1418
+ placement: "over",
1419
+ label: "\u02C7",
1420
+ title: "\u0639\u0644\u0627\u0645\u0629 \u062A\u062D\u0642\u0642"
1421
+ },
1422
+ breve: {
1423
+ id: "breve",
1424
+ englishTex: "\\breve",
1425
+ arabicTex: "\\breve",
1426
+ placement: "over",
1427
+ label: "\u02D8",
1428
+ title: "\u0642\u0648\u0633 \u0642\u0635\u064A\u0631"
1429
+ },
1430
+ acute: {
1431
+ id: "acute",
1432
+ englishTex: "\\acute",
1433
+ arabicTex: "\\grave",
1434
+ placement: "over",
1435
+ label: "\xB4",
1436
+ title: "\u0646\u0628\u0631\u0629 \u062D\u0627\u062F\u0629"
1437
+ },
1438
+ grave: {
1439
+ id: "grave",
1440
+ englishTex: "\\grave",
1441
+ arabicTex: "\\acute",
1442
+ placement: "over",
1443
+ label: "`",
1444
+ title: "\u0646\u0628\u0631\u0629 \u062B\u0642\u064A\u0644\u0629"
1445
+ },
1446
+ overline: {
1447
+ id: "overline",
1448
+ englishTex: "\\overline",
1449
+ arabicTex: "\\overline",
1450
+ placement: "over",
1451
+ label: "\u203E",
1452
+ title: "\u062E\u0637 \u0639\u0644\u0648\u064A \u0645\u0645\u062A\u062F"
1453
+ },
1454
+ underline: {
1455
+ id: "underline",
1456
+ englishTex: "\\underline",
1457
+ arabicTex: "\\underline",
1458
+ placement: "under",
1459
+ label: "_",
1460
+ title: "\u062E\u0637 \u0633\u0641\u0644\u064A"
1461
+ },
1462
+ overleftarrow: {
1463
+ id: "overleftarrow",
1464
+ englishTex: "\\overleftarrow",
1465
+ arabicTex: "\\overrightarrow",
1466
+ placement: "over",
1467
+ label: "\u2190",
1468
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631"
1469
+ },
1470
+ overrightarrow: {
1471
+ id: "overrightarrow",
1472
+ englishTex: "\\overrightarrow",
1473
+ arabicTex: "\\overleftarrow",
1474
+ placement: "over",
1475
+ label: "\u2192",
1476
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646"
1477
+ },
1478
+ overleftrightarrow: {
1479
+ id: "overleftrightarrow",
1480
+ englishTex: "\\overleftrightarrow",
1481
+ arabicTex: "\\overleftrightarrow",
1482
+ placement: "over",
1483
+ label: "\u2194",
1484
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0645\u0632\u062F\u0648\u062C \u0627\u0644\u0627\u062A\u062C\u0627\u0647"
1485
+ }
1486
+ };
1487
+ function accentCommandSpec(id) {
1488
+ return Object.prototype.hasOwnProperty.call(ACCENT_COMMANDS, id) ? ACCENT_COMMANDS[id] : null;
1489
+ }
1490
+ function accentCommandIdFromTex(tex) {
1491
+ const normalized = tex.startsWith("\\") ? tex : `\\${tex}`;
1492
+ for (const spec of Object.values(ACCENT_COMMANDS)) {
1493
+ if (spec.englishTex === normalized) {
1494
+ return spec.id;
1495
+ }
1496
+ }
1497
+ for (const spec of Object.values(ACCENT_COMMANDS)) {
1498
+ if (spec.arabicTex === normalized) {
1499
+ return spec.id;
1500
+ }
1501
+ }
1502
+ return null;
1503
+ }
1504
+
1356
1505
  // src/editor/atomicCommands.ts
1357
1506
  var ATOMIC_COMMANDS = {
1358
1507
  ///////////////////////// Functions ////////////////////////////////
@@ -1767,7 +1916,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1767
1916
  id: "neq",
1768
1917
  category: "operators1",
1769
1918
  Tex: "\\neq",
1770
- mirror: false,
1919
+ mirror: true,
1771
1920
  Label: "\u2260",
1772
1921
  title: "\u0644\u0627 \u064A\u0633\u0627\u0648\u064A",
1773
1922
  svg_path: null
@@ -1777,6 +1926,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1777
1926
  category: "operators1",
1778
1927
  Tex: "\\approx",
1779
1928
  mirror: false,
1929
+ displayMirror: true,
1780
1930
  Label: "\u2248",
1781
1931
  title: "\u062A\u0642\u0631\u064A\u0628\u0627 \u064A\u0633\u0627\u0648\u064A",
1782
1932
  svg_path: null
@@ -1786,6 +1936,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1786
1936
  category: "operators1",
1787
1937
  Tex: "\\sim",
1788
1938
  mirror: false,
1939
+ displayMirror: true,
1789
1940
  Label: "\u223C",
1790
1941
  title: "\u0645\u0634\u0627\u0628\u0647",
1791
1942
  svg_path: null
@@ -1804,6 +1955,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1804
1955
  category: "operators1",
1805
1956
  Tex: "\\leq",
1806
1957
  mirror: true,
1958
+ displayMirror: false,
1807
1959
  Label: "\u2264",
1808
1960
  title: "\u0623\u0635\u063A\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
1809
1961
  svg_path: null
@@ -1813,6 +1965,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1813
1965
  category: "operators1",
1814
1966
  Tex: "\\geq",
1815
1967
  mirror: true,
1968
+ displayMirror: false,
1816
1969
  Label: "\u2265",
1817
1970
  title: "\u0623\u0643\u0628\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
1818
1971
  svg_path: null
@@ -1822,6 +1975,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1822
1975
  category: "operators1",
1823
1976
  Tex: "\\coloneqq",
1824
1977
  mirror: true,
1978
+ displayMirror: false,
1825
1979
  Label: "\u2254",
1826
1980
  title: "\u064A\u0639\u0631\u0641 \u0628\u0623\u0646\u0647 \u064A\u0633\u0627\u0648\u064A",
1827
1981
  svg_path: null
@@ -1831,6 +1985,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1831
1985
  category: "operators1",
1832
1986
  Tex: "\\eqqcolon",
1833
1987
  mirror: true,
1988
+ displayMirror: false,
1834
1989
  Label: "\u2255",
1835
1990
  title: "\u064A\u0633\u0627\u0648\u064A \u0628\u0627\u0644\u062A\u0639\u0631\u064A\u0641",
1836
1991
  svg_path: null
@@ -1841,6 +1996,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1841
1996
  category: "operators2",
1842
1997
  Tex: "\\propto",
1843
1998
  mirror: true,
1999
+ displayMirror: false,
1844
2000
  Label: "\u221D",
1845
2001
  title: "\u064A\u062A\u0646\u0627\u0633\u0628 \u0645\u0639",
1846
2002
  svg_path: null
@@ -1850,6 +2006,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1850
2006
  category: "operators2",
1851
2007
  Tex: "\\in",
1852
2008
  mirror: true,
2009
+ displayMirror: false,
1853
2010
  Label: "\u2208",
1854
2011
  title: "\u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
1855
2012
  svg_path: null
@@ -1859,6 +2016,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1859
2016
  category: "operators2",
1860
2017
  Tex: "\\notin",
1861
2018
  mirror: false,
2019
+ displayMirror: true,
1862
2020
  Label: "\u2209",
1863
2021
  title: "\u0644\u0627 \u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
1864
2022
  svg_path: null
@@ -1868,6 +2026,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1868
2026
  category: "operators2",
1869
2027
  Tex: "\\subset",
1870
2028
  mirror: true,
2029
+ displayMirror: false,
1871
2030
  Label: "\u2282",
1872
2031
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0645\u0646",
1873
2032
  svg_path: null
@@ -1877,6 +2036,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1877
2036
  category: "operators2",
1878
2037
  Tex: "\\supset",
1879
2038
  mirror: true,
2039
+ displayMirror: false,
1880
2040
  Label: "\u2283",
1881
2041
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0644\u0640",
1882
2042
  svg_path: null
@@ -1886,6 +2046,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1886
2046
  category: "operators2",
1887
2047
  Tex: "\\subseteq",
1888
2048
  mirror: true,
2049
+ displayMirror: false,
1889
2050
  Label: "\u2286",
1890
2051
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1891
2052
  svg_path: null
@@ -1895,6 +2056,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1895
2056
  category: "operators2",
1896
2057
  Tex: "\\supseteq",
1897
2058
  mirror: true,
2059
+ displayMirror: false,
1898
2060
  Label: "\u2287",
1899
2061
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1900
2062
  svg_path: null
@@ -1904,6 +2066,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1904
2066
  category: "operators2",
1905
2067
  Tex: "\\cap",
1906
2068
  mirror: false,
2069
+ displayMirror: true,
1907
2070
  Label: "\u2229",
1908
2071
  title: "\u062A\u0642\u0627\u0637\u0639",
1909
2072
  svg_path: null
@@ -1913,6 +2076,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1913
2076
  category: "operators2",
1914
2077
  Tex: "\\cup",
1915
2078
  mirror: false,
2079
+ displayMirror: true,
1916
2080
  Label: "\u222A",
1917
2081
  title: "\u0627\u062A\u062D\u0627\u062F",
1918
2082
  svg_path: null
@@ -1922,6 +2086,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1922
2086
  category: "operators2",
1923
2087
  Tex: "\\emptyset",
1924
2088
  mirror: false,
2089
+ displayMirror: true,
1925
2090
  Label: "\u2205",
1926
2091
  title: "\u0627\u0644\u0645\u062C\u0645\u0648\u0639\u0629 \u0627\u0644\u062E\u0627\u0644\u064A\u0629",
1927
2092
  svg_path: null
@@ -1931,6 +2096,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1931
2096
  category: "operators2",
1932
2097
  Tex: "\\nsubseteq",
1933
2098
  mirror: true,
2099
+ displayMirror: false,
1934
2100
  Label: "\u2288",
1935
2101
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1936
2102
  svg_path: null
@@ -1940,6 +2106,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1940
2106
  category: "operators2",
1941
2107
  Tex: "\\nsupseteq",
1942
2108
  mirror: true,
2109
+ displayMirror: false,
1943
2110
  Label: "\u2289",
1944
2111
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1945
2112
  svg_path: null
@@ -2151,6 +2318,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2151
2318
  category: "integrals",
2152
2319
  Tex: "\\iint",
2153
2320
  mirror: true,
2321
+ displayMirror: false,
2154
2322
  Label: "\u222C",
2155
2323
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u0632\u062F\u0648\u062C",
2156
2324
  svg_path: null
@@ -2160,6 +2328,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2160
2328
  category: "integrals",
2161
2329
  Tex: "\\iiint",
2162
2330
  mirror: true,
2331
+ displayMirror: false,
2163
2332
  Label: "\u222D",
2164
2333
  title: "\u062A\u0643\u0627\u0645\u0644 \u062B\u0644\u0627\u062B\u064A",
2165
2334
  svg_path: null
@@ -2169,6 +2338,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2169
2338
  category: "integrals",
2170
2339
  Tex: "\\iiiint",
2171
2340
  mirror: true,
2341
+ displayMirror: false,
2172
2342
  Label: "\u2A0C",
2173
2343
  title: "\u062A\u0643\u0627\u0645\u0644 \u0631\u0628\u0627\u0639\u064A",
2174
2344
  svg_path: null
@@ -2178,6 +2348,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2178
2348
  category: "integrals",
2179
2349
  Tex: "\\oint",
2180
2350
  mirror: true,
2351
+ displayMirror: false,
2181
2352
  Label: "\u222E",
2182
2353
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u063A\u0644\u0642",
2183
2354
  svg_path: null
@@ -2187,6 +2358,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2187
2358
  category: "integrals",
2188
2359
  Tex: "\\oiint",
2189
2360
  mirror: true,
2361
+ displayMirror: false,
2190
2362
  Label: "\u222F",
2191
2363
  title: "\u062A\u0643\u0627\u0645\u0644 \u0633\u0637\u062D\u064A \u0645\u063A\u0644\u0642",
2192
2364
  svg_path: null
@@ -2196,6 +2368,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2196
2368
  category: "integrals",
2197
2369
  Tex: "\\oiiint",
2198
2370
  mirror: true,
2371
+ displayMirror: false,
2199
2372
  Label: "\u2230",
2200
2373
  title: "\u062A\u0643\u0627\u0645\u0644 \u062D\u062C\u0645\u064A \u0645\u063A\u0644\u0642",
2201
2374
  svg_path: null
@@ -2234,6 +2407,9 @@ function createEditorNode(kind, expr) {
2234
2407
  denominator: null,
2235
2408
  radicand: null,
2236
2409
  rootIndex: null,
2410
+ overExpr: null,
2411
+ underExpr: null,
2412
+ baseExpr: null,
2237
2413
  envName: null,
2238
2414
  matrixStyle: null,
2239
2415
  matrixRows: null,
@@ -2262,6 +2438,26 @@ function createSqrtNode() {
2262
2438
  rootIndex: createEditorChain()
2263
2439
  };
2264
2440
  }
2441
+ function createOversetNode() {
2442
+ return {
2443
+ ...createEditorNode("overset", ""),
2444
+ overExpr: createEditorChain(),
2445
+ baseExpr: createEditorChain()
2446
+ };
2447
+ }
2448
+ function createUndersetNode() {
2449
+ return {
2450
+ ...createEditorNode("underset", ""),
2451
+ underExpr: createEditorChain(),
2452
+ baseExpr: createEditorChain()
2453
+ };
2454
+ }
2455
+ function createAccentNode(accentId) {
2456
+ return {
2457
+ ...createEditorNode("accent", accentId),
2458
+ baseExpr: createEditorChain()
2459
+ };
2460
+ }
2265
2461
  function createGridEnvNode(envName, rows, columns, columnAlignments) {
2266
2462
  const safeRows = Math.max(1, Math.min(12, Math.trunc(rows)));
2267
2463
  const safeColumns = Math.max(1, Math.min(12, Math.trunc(columns)));
@@ -2320,6 +2516,15 @@ function collectNodeIds(chain, ids) {
2320
2516
  if (node.radicand) {
2321
2517
  collectNodeIds(node.radicand, ids);
2322
2518
  }
2519
+ if (node.overExpr) {
2520
+ collectNodeIds(node.overExpr, ids);
2521
+ }
2522
+ if (node.underExpr) {
2523
+ collectNodeIds(node.underExpr, ids);
2524
+ }
2525
+ if (node.baseExpr) {
2526
+ collectNodeIds(node.baseExpr, ids);
2527
+ }
2323
2528
  if (node.matrixRows) {
2324
2529
  for (const row of node.matrixRows) {
2325
2530
  for (const cell of row) {
@@ -2450,6 +2655,22 @@ function renderMatrixRowsArabic(node, options) {
2450
2655
  }
2451
2656
  return `\\begin{${envName}}${rows.join(" \\\\\n")}\\end{${envName}}`;
2452
2657
  }
2658
+ function renderAccentEnglish(command, accent, base, options) {
2659
+ const baseTex = base ? renderChainEnglish(base, options) : "";
2660
+ const accentTex = accent ? renderChainEnglish(accent, options) : "";
2661
+ if (accentTex === "") {
2662
+ return baseTex;
2663
+ }
2664
+ return `\\${command}{${accentTex}}{${baseTex}}`;
2665
+ }
2666
+ function renderAccentArabic(command, accent, base, options) {
2667
+ const baseTex = base ? renderChainArabic(base, options) : "";
2668
+ const accentTex = accent ? renderChainArabic(accent, options) : "";
2669
+ if (accentTex === "") {
2670
+ return baseTex;
2671
+ }
2672
+ return `\\${command}{${accentTex}}{${baseTex}}`;
2673
+ }
2453
2674
  function escapeText(s) {
2454
2675
  return s.replace(/\\/g, "\\textbackslash{}").replace(/[{}]/g, "\\$&");
2455
2676
  }
@@ -2479,6 +2700,19 @@ function renderNodeEnglish(node, options) {
2479
2700
  const body = `\\sqrt${optionalRootIndexEnglish(node, options)}{${renderChainEnglish(node.radicand, options)}}`;
2480
2701
  return `${body}${latinScripts(node, options)}`;
2481
2702
  }
2703
+ if (node.kind === "overset" && node.baseExpr) {
2704
+ const body = renderAccentEnglish("overset", node.overExpr, node.baseExpr, options);
2705
+ return `${body}${latinScripts(node, options)}`;
2706
+ }
2707
+ if (node.kind === "underset" && node.baseExpr) {
2708
+ const body = renderAccentEnglish("underset", node.underExpr, node.baseExpr, options);
2709
+ return `${body}${latinScripts(node, options)}`;
2710
+ }
2711
+ if (node.kind === "accent" && node.baseExpr) {
2712
+ const cmd = accentCommandSpec(node.expr)?.englishTex ?? `\\${node.expr}`;
2713
+ const body = `${cmd}{${renderChainEnglish(node.baseExpr, options)}}`;
2714
+ return `${body}${latinScripts(node, options)}`;
2715
+ }
2482
2716
  if (node.kind === "env") {
2483
2717
  return `${renderMatrixRowsEnglish(node, options)}${latinScripts(node, options)}`;
2484
2718
  }
@@ -2511,6 +2745,19 @@ function renderNodeArabic(node, options) {
2511
2745
  const content = `\\arabsqrt${optionalRootIndexArabic(node, options)}{${renderChainArabic(node.radicand, options)}}`;
2512
2746
  return arabicScripts(node, content, options);
2513
2747
  }
2748
+ if (node.kind === "overset" && node.baseExpr) {
2749
+ const content = renderAccentArabic("overset", node.overExpr, node.baseExpr, options);
2750
+ return arabicScripts(node, content, options);
2751
+ }
2752
+ if (node.kind === "underset" && node.baseExpr) {
2753
+ const content = renderAccentArabic("underset", node.underExpr, node.baseExpr, options);
2754
+ return arabicScripts(node, content, options);
2755
+ }
2756
+ if (node.kind === "accent" && node.baseExpr) {
2757
+ const cmd = accentCommandSpec(node.expr)?.arabicTex ?? `\\${node.expr}`;
2758
+ const content = `${cmd}{${renderChainArabic(node.baseExpr, options)}}`;
2759
+ return arabicScripts(node, content, options);
2760
+ }
2514
2761
  if (node.kind === "env") {
2515
2762
  return arabicScripts(node, renderMatrixRowsArabic(node, options), options);
2516
2763
  }
@@ -2715,6 +2962,109 @@ var SQRT_CSS = `
2715
2962
  }
2716
2963
  `.trim();
2717
2964
 
2965
+ // src/editor/display/overset.ts
2966
+ var OVERSET_CSS = `
2967
+ .overset {
2968
+ display: inline-flex;
2969
+ flex-direction: column;
2970
+ align-items: center;
2971
+ justify-content: center;
2972
+ vertical-align: middle;
2973
+ margin: 0 2px;
2974
+ min-width: 1.2em;
2975
+ }
2976
+
2977
+ .overset-over {
2978
+ display: inline-flex;
2979
+ justify-content: center;
2980
+ align-items: center;
2981
+ min-height: 0.85em;
2982
+ padding: 0 2px;
2983
+ font-size: 0.72em;
2984
+ line-height: 1.1;
2985
+ }
2986
+
2987
+ .overset-base {
2988
+ display: inline-flex;
2989
+ justify-content: center;
2990
+ align-items: center;
2991
+ min-height: 1.05em;
2992
+ padding: 0 2px;
2993
+ }
2994
+ `.trim();
2995
+
2996
+ // src/editor/display/underset.ts
2997
+ var UNDERSET_CSS = `
2998
+ .underset {
2999
+ display: inline-flex;
3000
+ flex-direction: column;
3001
+ align-items: center;
3002
+ justify-content: center;
3003
+ vertical-align: middle;
3004
+ margin: 0 2px;
3005
+ min-width: 1.2em;
3006
+ }
3007
+
3008
+ .underset-base {
3009
+ display: inline-flex;
3010
+ justify-content: center;
3011
+ align-items: center;
3012
+ min-height: 1.05em;
3013
+ padding: 0 2px;
3014
+ }
3015
+
3016
+ .underset-under {
3017
+ display: inline-flex;
3018
+ justify-content: center;
3019
+ align-items: center;
3020
+ min-height: 0.85em;
3021
+ padding: 0 2px;
3022
+ font-size: 0.72em;
3023
+ line-height: 1.1;
3024
+ }
3025
+ `.trim();
3026
+
3027
+ // src/editor/display/accent.ts
3028
+ var ACCENT_CSS = `
3029
+ .math-accent {
3030
+ display: inline-flex;
3031
+ flex-direction: column;
3032
+ align-items: center;
3033
+ justify-content: center;
3034
+ vertical-align: middle;
3035
+ margin: 0 2px;
3036
+ min-width: 1.1em;
3037
+ }
3038
+
3039
+ .math-accent-chrome {
3040
+ display: inline-flex;
3041
+ justify-content: center;
3042
+ align-items: center;
3043
+ min-height: 0.7em;
3044
+ padding: 0 2px;
3045
+ font-size: 0.85em;
3046
+ line-height: 1;
3047
+ color: var(--butex-script-color, #475569);
3048
+ user-select: none;
3049
+ }
3050
+
3051
+ .math-accent-base {
3052
+ display: inline-flex;
3053
+ justify-content: center;
3054
+ align-items: center;
3055
+ min-height: 1.05em;
3056
+ padding: 0 2px;
3057
+ }
3058
+
3059
+ .math-accent--under .math-accent-chrome {
3060
+ min-height: 0.45em;
3061
+ border-top: 1.5px solid currentColor;
3062
+ width: 100%;
3063
+ font-size: 0;
3064
+ color: var(--butex-surface-fg, #0f172a);
3065
+ }
3066
+ `.trim();
3067
+
2718
3068
  // src/editor/display/env.ts
2719
3069
  var MATRIX_ENV_CSS = `
2720
3070
  .matrix-env {
@@ -3102,6 +3452,12 @@ ${FRAC_CSS}
3102
3452
 
3103
3453
  ${SQRT_CSS}
3104
3454
 
3455
+ ${OVERSET_CSS}
3456
+
3457
+ ${UNDERSET_CSS}
3458
+
3459
+ ${ACCENT_CSS}
3460
+
3105
3461
  ${MATRIX_ENV_CSS}
3106
3462
 
3107
3463
  ${ATOMIC_COMMAND_CSS}
@@ -3384,6 +3740,56 @@ function commandToEditorNode(node) {
3384
3740
  }
3385
3741
  return { editable: true, node: sqrt };
3386
3742
  }
3743
+ if (node.name === "\\overset" && node.mandatoryArgs.length >= 2) {
3744
+ const overset = createOversetNode();
3745
+ const overExpr = chainToEditorChain(node.mandatoryArgs[0]);
3746
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[1]);
3747
+ if (!overExpr.editable) {
3748
+ return overExpr;
3749
+ }
3750
+ if (!baseExpr.editable) {
3751
+ return baseExpr;
3752
+ }
3753
+ overset.overExpr = overExpr.chain;
3754
+ overset.baseExpr = baseExpr.chain;
3755
+ const scripts = attachScripts(node, overset);
3756
+ if (scripts) {
3757
+ return scripts;
3758
+ }
3759
+ return { editable: true, node: overset };
3760
+ }
3761
+ if (node.name === "\\underset" && node.mandatoryArgs.length >= 2) {
3762
+ const underset = createUndersetNode();
3763
+ const underExpr = chainToEditorChain(node.mandatoryArgs[0]);
3764
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[1]);
3765
+ if (!underExpr.editable) {
3766
+ return underExpr;
3767
+ }
3768
+ if (!baseExpr.editable) {
3769
+ return baseExpr;
3770
+ }
3771
+ underset.underExpr = underExpr.chain;
3772
+ underset.baseExpr = baseExpr.chain;
3773
+ const scripts = attachScripts(node, underset);
3774
+ if (scripts) {
3775
+ return scripts;
3776
+ }
3777
+ return { editable: true, node: underset };
3778
+ }
3779
+ const accentId = accentCommandIdFromTex(node.name);
3780
+ if (accentId && node.mandatoryArgs.length >= 1) {
3781
+ const accent = createAccentNode(accentId);
3782
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[0]);
3783
+ if (!baseExpr.editable) {
3784
+ return baseExpr;
3785
+ }
3786
+ accent.baseExpr = baseExpr.chain;
3787
+ const scripts = attachScripts(node, accent);
3788
+ if (scripts) {
3789
+ return scripts;
3790
+ }
3791
+ return { editable: true, node: accent };
3792
+ }
3387
3793
  const atomicId = commandIdForTex(node.name);
3388
3794
  if (atomicId && node.optionalArgs.length === 0 && node.mandatoryArgs.length === 0) {
3389
3795
  const atomic = createEditorNode("atomicCommand", atomicId);
@@ -3520,6 +3926,21 @@ function editorEnvToAstNode(node) {
3520
3926
  const scripts = attachAstScripts(node, env);
3521
3927
  return scripts ?? { ok: true, node: env };
3522
3928
  }
3929
+ function accentChainForExport(accent) {
3930
+ if (!accent) {
3931
+ return { ok: true, chain: new ChainNode([]) };
3932
+ }
3933
+ return editorChainToAstChain(accent);
3934
+ }
3935
+ function nodeFromAccentBase(command, accent, base) {
3936
+ if (accent.chain.length > 0) {
3937
+ return new CommandNode(command, [], [accent, base]);
3938
+ }
3939
+ if (base.chain.length === 1) {
3940
+ return base.chain[0];
3941
+ }
3942
+ return new DelimiterNode("", base, "");
3943
+ }
3523
3944
  function editorNodeToAstNode(node) {
3524
3945
  let astNode;
3525
3946
  if (node.kind === "char") {
@@ -3558,6 +3979,36 @@ function editorNodeToAstNode(node) {
3558
3979
  optionalArgs.push(rootIndex.chain);
3559
3980
  }
3560
3981
  astNode = new CommandNode("\\sqrt", optionalArgs, [radicand.chain]);
3982
+ } else if (node.kind === "overset" && node.baseExpr) {
3983
+ const accent = accentChainForExport(node.overExpr);
3984
+ if (!accent.ok) {
3985
+ return accent;
3986
+ }
3987
+ const baseExpr = editorChainToAstChain(node.baseExpr);
3988
+ if (!baseExpr.ok) {
3989
+ return baseExpr;
3990
+ }
3991
+ astNode = nodeFromAccentBase("\\overset", accent.chain, baseExpr.chain);
3992
+ } else if (node.kind === "underset" && node.baseExpr) {
3993
+ const accent = accentChainForExport(node.underExpr);
3994
+ if (!accent.ok) {
3995
+ return accent;
3996
+ }
3997
+ const baseExpr = editorChainToAstChain(node.baseExpr);
3998
+ if (!baseExpr.ok) {
3999
+ return baseExpr;
4000
+ }
4001
+ astNode = nodeFromAccentBase("\\underset", accent.chain, baseExpr.chain);
4002
+ } else if (node.kind === "accent" && node.baseExpr) {
4003
+ const tex = accentCommandSpec(node.expr)?.englishTex;
4004
+ if (!tex) {
4005
+ return { ok: false, reason: `\u0644\u0643\u0646\u0629 \u0631\u064A\u0627\u0636\u064A\u0629 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645\u0629 \u062D\u0627\u0644\u064A\u0627: ${node.expr}` };
4006
+ }
4007
+ const baseExpr = editorChainToAstChain(node.baseExpr);
4008
+ if (!baseExpr.ok) {
4009
+ return baseExpr;
4010
+ }
4011
+ astNode = new CommandNode(tex, [], [baseExpr.chain]);
3561
4012
  } else if (node.kind === "atomicCommand") {
3562
4013
  const tex = atomicCommandSpec(node.expr)?.englishTex;
3563
4014
  if (!tex) {