@drghaliasri/butex 5.3.3 → 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.
package/dist/index.js CHANGED
@@ -787,11 +787,20 @@ function passthroughArgument(parser, name) {
787
787
  const inner = new TexParserClass(arg, parser.stack.env, parser.configuration).mml();
788
788
  parser.Push(inner);
789
789
  }
790
+ function arabvecArgument(parser, name) {
791
+ const arg = parser.GetArgument(name);
792
+ const TexParserClass = parser.constructor;
793
+ const tex = `\\butexmirror{\\vec{\\butexmirror{${arg}}}}`;
794
+ const inner = new TexParserClass(tex, parser.stack.env, parser.configuration).mml();
795
+ parser.Push(inner);
796
+ }
790
797
  var passthroughArgumentTyped = passthroughArgument;
798
+ var arabvecArgumentTyped = arabvecArgument;
791
799
  function registerPassthroughCommandMacros(CommandMap) {
792
800
  new CommandMap(COMMAND_MAP6, {
793
801
  unit: passthroughArgumentTyped,
794
- idx: passthroughArgumentTyped
802
+ idx: passthroughArgumentTyped,
803
+ arabvec: arabvecArgumentTyped
795
804
  });
796
805
  return COMMAND_MAP6;
797
806
  }
@@ -1117,6 +1126,320 @@ function buildSqrtNodeBody(node, buildChain, side) {
1117
1126
  return wrap;
1118
1127
  }
1119
1128
 
1129
+ // src/editor/display/overset.ts
1130
+ var OVERSET_CSS = `
1131
+ .overset {
1132
+ display: inline-flex;
1133
+ flex-direction: column;
1134
+ align-items: center;
1135
+ justify-content: center;
1136
+ vertical-align: middle;
1137
+ margin: 0 2px;
1138
+ min-width: 1.2em;
1139
+ }
1140
+
1141
+ .overset-over {
1142
+ display: inline-flex;
1143
+ justify-content: center;
1144
+ align-items: center;
1145
+ min-height: 0.85em;
1146
+ padding: 0 2px;
1147
+ font-size: 0.72em;
1148
+ line-height: 1.1;
1149
+ }
1150
+
1151
+ .overset-base {
1152
+ display: inline-flex;
1153
+ justify-content: center;
1154
+ align-items: center;
1155
+ min-height: 1.05em;
1156
+ padding: 0 2px;
1157
+ }
1158
+ `.trim();
1159
+ function buildOversetNodeBody(node, buildChain) {
1160
+ const wrap = document.createElement("span");
1161
+ wrap.className = "overset";
1162
+ const over = document.createElement("span");
1163
+ over.className = "overset-over";
1164
+ if (node.overExpr) {
1165
+ over.appendChild(buildChain(node.overExpr));
1166
+ }
1167
+ const base = document.createElement("span");
1168
+ base.className = "overset-base";
1169
+ if (node.baseExpr) {
1170
+ base.appendChild(buildChain(node.baseExpr));
1171
+ }
1172
+ wrap.appendChild(over);
1173
+ wrap.appendChild(base);
1174
+ return wrap;
1175
+ }
1176
+
1177
+ // src/editor/display/underset.ts
1178
+ var UNDERSET_CSS = `
1179
+ .underset {
1180
+ display: inline-flex;
1181
+ flex-direction: column;
1182
+ align-items: center;
1183
+ justify-content: center;
1184
+ vertical-align: middle;
1185
+ margin: 0 2px;
1186
+ min-width: 1.2em;
1187
+ }
1188
+
1189
+ .underset-base {
1190
+ display: inline-flex;
1191
+ justify-content: center;
1192
+ align-items: center;
1193
+ min-height: 1.05em;
1194
+ padding: 0 2px;
1195
+ }
1196
+
1197
+ .underset-under {
1198
+ display: inline-flex;
1199
+ justify-content: center;
1200
+ align-items: center;
1201
+ min-height: 0.85em;
1202
+ padding: 0 2px;
1203
+ font-size: 0.72em;
1204
+ line-height: 1.1;
1205
+ }
1206
+ `.trim();
1207
+ function buildUndersetNodeBody(node, buildChain) {
1208
+ const wrap = document.createElement("span");
1209
+ wrap.className = "underset";
1210
+ const base = document.createElement("span");
1211
+ base.className = "underset-base";
1212
+ if (node.baseExpr) {
1213
+ base.appendChild(buildChain(node.baseExpr));
1214
+ }
1215
+ const under = document.createElement("span");
1216
+ under.className = "underset-under";
1217
+ if (node.underExpr) {
1218
+ under.appendChild(buildChain(node.underExpr));
1219
+ }
1220
+ wrap.appendChild(base);
1221
+ wrap.appendChild(under);
1222
+ return wrap;
1223
+ }
1224
+
1225
+ // src/editor/accentCommands.ts
1226
+ var ACCENT_COMMANDS = {
1227
+ vec: {
1228
+ id: "vec",
1229
+ englishTex: "\\vec",
1230
+ arabicTex: "\\arabvec",
1231
+ placement: "over",
1232
+ label: "\u20D7",
1233
+ title: "\u0633\u0647\u0645 \u0641\u0648\u0642"
1234
+ },
1235
+ hat: {
1236
+ id: "hat",
1237
+ englishTex: "\\hat",
1238
+ arabicTex: "\\hat",
1239
+ placement: "over",
1240
+ label: "\u02C6",
1241
+ title: "\u0642\u0628\u0639\u0629"
1242
+ },
1243
+ tilde: {
1244
+ id: "tilde",
1245
+ englishTex: "\\tilde",
1246
+ arabicTex: "\\tilde",
1247
+ placement: "over",
1248
+ label: "\u02DC",
1249
+ title: "\u0645\u062F\u0629"
1250
+ },
1251
+ dot: {
1252
+ id: "dot",
1253
+ englishTex: "\\dot",
1254
+ arabicTex: "\\dot",
1255
+ placement: "over",
1256
+ label: "\u02D9",
1257
+ title: "\u0646\u0642\u0637\u0629 \u0641\u0648\u0642"
1258
+ },
1259
+ ddot: {
1260
+ id: "ddot",
1261
+ englishTex: "\\ddot",
1262
+ arabicTex: "\\ddot",
1263
+ placement: "over",
1264
+ label: "\xA8",
1265
+ title: "\u0646\u0642\u0637\u062A\u0627\u0646 \u0641\u0648\u0642"
1266
+ },
1267
+ dddot: {
1268
+ id: "dddot",
1269
+ englishTex: "\\dddot",
1270
+ arabicTex: "\\dddot",
1271
+ placement: "over",
1272
+ label: "\u20DB",
1273
+ title: "\u062B\u0644\u0627\u062B \u0646\u0642\u0627\u0637 \u0641\u0648\u0642"
1274
+ },
1275
+ bar: {
1276
+ id: "bar",
1277
+ englishTex: "\\bar",
1278
+ arabicTex: "\\bar",
1279
+ placement: "over",
1280
+ label: "\xAF",
1281
+ title: "\u062E\u0637 \u0641\u0648\u0642"
1282
+ },
1283
+ check: {
1284
+ id: "check",
1285
+ englishTex: "\\check",
1286
+ arabicTex: "\\check",
1287
+ placement: "over",
1288
+ label: "\u02C7",
1289
+ title: "\u0639\u0644\u0627\u0645\u0629 \u062A\u062D\u0642\u0642"
1290
+ },
1291
+ breve: {
1292
+ id: "breve",
1293
+ englishTex: "\\breve",
1294
+ arabicTex: "\\breve",
1295
+ placement: "over",
1296
+ label: "\u02D8",
1297
+ title: "\u0642\u0648\u0633 \u0642\u0635\u064A\u0631"
1298
+ },
1299
+ acute: {
1300
+ id: "acute",
1301
+ englishTex: "\\acute",
1302
+ arabicTex: "\\grave",
1303
+ placement: "over",
1304
+ label: "\xB4",
1305
+ title: "\u0646\u0628\u0631\u0629 \u062D\u0627\u062F\u0629"
1306
+ },
1307
+ grave: {
1308
+ id: "grave",
1309
+ englishTex: "\\grave",
1310
+ arabicTex: "\\acute",
1311
+ placement: "over",
1312
+ label: "`",
1313
+ title: "\u0646\u0628\u0631\u0629 \u062B\u0642\u064A\u0644\u0629"
1314
+ },
1315
+ overline: {
1316
+ id: "overline",
1317
+ englishTex: "\\overline",
1318
+ arabicTex: "\\overline",
1319
+ placement: "over",
1320
+ label: "\u203E",
1321
+ title: "\u062E\u0637 \u0639\u0644\u0648\u064A \u0645\u0645\u062A\u062F"
1322
+ },
1323
+ underline: {
1324
+ id: "underline",
1325
+ englishTex: "\\underline",
1326
+ arabicTex: "\\underline",
1327
+ placement: "under",
1328
+ label: "_",
1329
+ title: "\u062E\u0637 \u0633\u0641\u0644\u064A"
1330
+ },
1331
+ overleftarrow: {
1332
+ id: "overleftarrow",
1333
+ englishTex: "\\overleftarrow",
1334
+ arabicTex: "\\overrightarrow",
1335
+ placement: "over",
1336
+ label: "\u2190",
1337
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631"
1338
+ },
1339
+ overrightarrow: {
1340
+ id: "overrightarrow",
1341
+ englishTex: "\\overrightarrow",
1342
+ arabicTex: "\\overleftarrow",
1343
+ placement: "over",
1344
+ label: "\u2192",
1345
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646"
1346
+ },
1347
+ overleftrightarrow: {
1348
+ id: "overleftrightarrow",
1349
+ englishTex: "\\overleftrightarrow",
1350
+ arabicTex: "\\overleftrightarrow",
1351
+ placement: "over",
1352
+ label: "\u2194",
1353
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0645\u0632\u062F\u0648\u062C \u0627\u0644\u0627\u062A\u062C\u0627\u0647"
1354
+ }
1355
+ };
1356
+ function accentCommandSpec(id) {
1357
+ return Object.prototype.hasOwnProperty.call(ACCENT_COMMANDS, id) ? ACCENT_COMMANDS[id] : null;
1358
+ }
1359
+ function accentCommandsList() {
1360
+ return Object.values(ACCENT_COMMANDS);
1361
+ }
1362
+ function accentCommandIdFromTex(tex) {
1363
+ const normalized = tex.startsWith("\\") ? tex : `\\${tex}`;
1364
+ for (const spec of Object.values(ACCENT_COMMANDS)) {
1365
+ if (spec.englishTex === normalized) {
1366
+ return spec.id;
1367
+ }
1368
+ }
1369
+ for (const spec of Object.values(ACCENT_COMMANDS)) {
1370
+ if (spec.arabicTex === normalized) {
1371
+ return spec.id;
1372
+ }
1373
+ }
1374
+ return null;
1375
+ }
1376
+
1377
+ // src/editor/display/accent.ts
1378
+ var ACCENT_CSS = `
1379
+ .math-accent {
1380
+ display: inline-flex;
1381
+ flex-direction: column;
1382
+ align-items: center;
1383
+ justify-content: center;
1384
+ vertical-align: middle;
1385
+ margin: 0 2px;
1386
+ min-width: 1.1em;
1387
+ }
1388
+
1389
+ .math-accent-chrome {
1390
+ display: inline-flex;
1391
+ justify-content: center;
1392
+ align-items: center;
1393
+ min-height: 0.7em;
1394
+ padding: 0 2px;
1395
+ font-size: 0.85em;
1396
+ line-height: 1;
1397
+ color: var(--butex-script-color, #475569);
1398
+ user-select: none;
1399
+ }
1400
+
1401
+ .math-accent-base {
1402
+ display: inline-flex;
1403
+ justify-content: center;
1404
+ align-items: center;
1405
+ min-height: 1.05em;
1406
+ padding: 0 2px;
1407
+ }
1408
+
1409
+ .math-accent--under .math-accent-chrome {
1410
+ min-height: 0.45em;
1411
+ border-top: 1.5px solid currentColor;
1412
+ width: 100%;
1413
+ font-size: 0;
1414
+ color: var(--butex-surface-fg, #0f172a);
1415
+ }
1416
+ `.trim();
1417
+ function buildAccentNodeBody(node, buildChain) {
1418
+ const wrap = document.createElement("span");
1419
+ const spec = accentCommandSpec(node.expr);
1420
+ const placement = spec?.placement ?? "over";
1421
+ wrap.className = placement === "under" ? "math-accent math-accent--under" : "math-accent math-accent--over";
1422
+ const chrome = document.createElement("span");
1423
+ chrome.className = "math-accent-chrome";
1424
+ chrome.setAttribute("aria-hidden", "true");
1425
+ if (placement === "over") {
1426
+ chrome.textContent = spec?.label ?? "\u02C6";
1427
+ }
1428
+ const base = document.createElement("span");
1429
+ base.className = "math-accent-base";
1430
+ if (node.baseExpr) {
1431
+ base.appendChild(buildChain(node.baseExpr));
1432
+ }
1433
+ if (placement === "under") {
1434
+ wrap.appendChild(base);
1435
+ wrap.appendChild(chrome);
1436
+ } else {
1437
+ wrap.appendChild(chrome);
1438
+ wrap.appendChild(base);
1439
+ }
1440
+ return wrap;
1441
+ }
1442
+
1120
1443
  // src/editor/display/env.ts
1121
1444
  var WRAPPERS = {
1122
1445
  matrix: { left: "", right: "" },
@@ -1342,6 +1665,10 @@ var EQUATION_EDITOR_MESSAGES = {
1342
1665
  insertBraces: "\u0625\u062F\u0631\u0627\u062C \u062D\u0627\u0635\u0631\u062A\u064A\u0646",
1343
1666
  insertFraction: "\u0625\u062F\u0631\u0627\u062C \u0643\u0633\u0631",
1344
1667
  insertRoot: "\u0625\u062F\u0631\u0627\u062C \u062C\u0630\u0631",
1668
+ insertOverset: "\u0625\u062F\u0631\u0627\u062C \u0641\u0648\u0642",
1669
+ insertUnderset: "\u0625\u062F\u0631\u0627\u062C \u062A\u062D\u062A",
1670
+ insertAccentPair: "\u0625\u062F\u0631\u0627\u062C \u0641\u0648\u0642 \u0648\u062A\u062D\u062A",
1671
+ insertAccents: "\u0625\u062F\u0631\u0627\u062C \u0644\u0643\u0646\u0629",
1345
1672
  environments: "\u0627\u0644\u0628\u064A\u0626\u0627\u062A",
1346
1673
  insertEnvironment: "\u0625\u062F\u0631\u0627\u062C \u0628\u064A\u0626\u0629 \u0634\u0628\u0643\u064A\u0629",
1347
1674
  environmentType: "\u0646\u0648\u0639 \u0627\u0644\u0628\u064A\u0626\u0629",
@@ -1449,6 +1776,10 @@ var EQUATION_EDITOR_MESSAGES = {
1449
1776
  insertBraces: "Insert braces",
1450
1777
  insertFraction: "Insert fraction",
1451
1778
  insertRoot: "Insert root",
1779
+ insertOverset: "Insert overset",
1780
+ insertUnderset: "Insert underset",
1781
+ insertAccentPair: "Insert overset and underset",
1782
+ insertAccents: "Insert accent",
1452
1783
  environments: "Environments",
1453
1784
  insertEnvironment: "Insert grid environment",
1454
1785
  environmentType: "Environment type",
@@ -2485,6 +2816,12 @@ ${FRAC_CSS}
2485
2816
 
2486
2817
  ${SQRT_CSS}
2487
2818
 
2819
+ ${OVERSET_CSS}
2820
+
2821
+ ${UNDERSET_CSS}
2822
+
2823
+ ${ACCENT_CSS}
2824
+
2488
2825
  ${MATRIX_ENV_CSS}
2489
2826
 
2490
2827
  ${ATOMIC_COMMAND_CSS}
@@ -2511,6 +2848,8 @@ function injectBuTeXEditorStyles(doc) {
2511
2848
  // src/editor/index.ts
2512
2849
  var editor_exports = {};
2513
2850
  __export(editor_exports, {
2851
+ ACCENT_COMMANDS: () => ACCENT_COMMANDS,
2852
+ ACCENT_CSS: () => ACCENT_CSS,
2514
2853
  ATOMIC_COMMANDS: () => ATOMIC_COMMANDS,
2515
2854
  ATOMIC_COMMAND_CSS: () => ATOMIC_COMMAND_CSS,
2516
2855
  ATOMIC_OPERATOR_COMMANDS: () => ATOMIC_OPERATOR_COMMANDS,
@@ -2521,7 +2860,12 @@ __export(editor_exports, {
2521
2860
  DELIMITER_CSS: () => DELIMITER_CSS,
2522
2861
  FRAC_CSS: () => FRAC_CSS,
2523
2862
  MATRIX_ENV_CSS: () => MATRIX_ENV_CSS,
2863
+ OVERSET_CSS: () => OVERSET_CSS,
2524
2864
  SQRT_CSS: () => SQRT_CSS,
2865
+ UNDERSET_CSS: () => UNDERSET_CSS,
2866
+ accentCommandIdFromTex: () => accentCommandIdFromTex,
2867
+ accentCommandSpec: () => accentCommandSpec,
2868
+ accentCommandsList: () => accentCommandsList,
2525
2869
  activeSideLabel: () => activeSideLabel,
2526
2870
  activeTreeKey: () => activeTreeKey,
2527
2871
  addMatrixColumn: () => addMatrixColumn,
@@ -2542,6 +2886,7 @@ __export(editor_exports, {
2542
2886
  collectCaretPositions: () => collectCaretPositions,
2543
2887
  copySelection: () => copySelection,
2544
2888
  coveredNodeIds: () => coveredNodeIds,
2889
+ createAccentNode: () => createAccentNode,
2545
2890
  createAtomicCommandNode: () => createAtomicCommandNode,
2546
2891
  createAtomicOperatorCommandNode: () => createAtomicOperatorCommandNode,
2547
2892
  createDelimiterNode: () => createDelimiterNode,
@@ -2552,8 +2897,10 @@ __export(editor_exports, {
2552
2897
  createFracNode: () => createFracNode,
2553
2898
  createGridEnvNode: () => createGridEnvNode,
2554
2899
  createMatrixEnvNode: () => createMatrixEnvNode,
2900
+ createOversetNode: () => createOversetNode,
2555
2901
  createSqrtNode: () => createSqrtNode,
2556
2902
  createStarterSession: () => createStarterSession,
2903
+ createUndersetNode: () => createUndersetNode,
2557
2904
  createUndoRedoStacks: () => createUndoRedoStacks,
2558
2905
  cutSelection: () => cutSelection,
2559
2906
  deleteBackward: () => deleteBackward,
@@ -2567,6 +2914,8 @@ __export(editor_exports, {
2567
2914
  fragmentToPlainText: () => fragmentToPlainText,
2568
2915
  horizontalCaretDelta: () => horizontalCaretDelta,
2569
2916
  injectBuTeXEditorStyles: () => injectBuTeXEditorStyles,
2917
+ insertAccent: () => insertAccent,
2918
+ insertAccentPair: () => insertAccentPair,
2570
2919
  insertAlignedEnv: () => insertAlignedEnv,
2571
2920
  insertArrayEnv: () => insertArrayEnv,
2572
2921
  insertAtomicCommand: () => insertAtomicCommand,
@@ -2576,11 +2925,14 @@ __export(editor_exports, {
2576
2925
  insertDivideOperator: () => insertDivideOperator,
2577
2926
  insertFirstDerivative: () => insertFirstDerivative,
2578
2927
  insertFraction: () => insertFraction,
2928
+ insertLimitsSeriesTemplate: () => insertLimitsSeriesTemplate,
2579
2929
  insertMatrixEnv: () => insertMatrixEnv,
2580
2930
  insertNumber: () => insertNumber,
2581
2931
  insertOperator: () => insertOperator,
2932
+ insertOverset: () => insertOverset,
2582
2933
  insertSecondDerivative: () => insertSecondDerivative,
2583
2934
  insertSqrt: () => insertSqrt,
2935
+ insertUnderset: () => insertUnderset,
2584
2936
  isSelectionActive: () => isSelectionActive,
2585
2937
  isSpacingCommandSpec: () => isSpacingCommandSpec,
2586
2938
  mirrorBuTeXOperatorsInTex: () => mirrorBuTeXOperatorsInTex,
@@ -2654,6 +3006,9 @@ function createEditorNode(kind, expr) {
2654
3006
  denominator: null,
2655
3007
  radicand: null,
2656
3008
  rootIndex: null,
3009
+ overExpr: null,
3010
+ underExpr: null,
3011
+ baseExpr: null,
2657
3012
  envName: null,
2658
3013
  matrixStyle: null,
2659
3014
  matrixRows: null,
@@ -2682,6 +3037,26 @@ function createSqrtNode() {
2682
3037
  rootIndex: createEditorChain()
2683
3038
  };
2684
3039
  }
3040
+ function createOversetNode() {
3041
+ return {
3042
+ ...createEditorNode("overset", ""),
3043
+ overExpr: createEditorChain(),
3044
+ baseExpr: createEditorChain()
3045
+ };
3046
+ }
3047
+ function createUndersetNode() {
3048
+ return {
3049
+ ...createEditorNode("underset", ""),
3050
+ underExpr: createEditorChain(),
3051
+ baseExpr: createEditorChain()
3052
+ };
3053
+ }
3054
+ function createAccentNode(accentId) {
3055
+ return {
3056
+ ...createEditorNode("accent", accentId),
3057
+ baseExpr: createEditorChain()
3058
+ };
3059
+ }
2685
3060
  function createMatrixEnvNode(style, rows, columns) {
2686
3061
  return createGridEnvNode(style, rows, columns);
2687
3062
  }
@@ -2749,6 +3124,15 @@ function collectNodeIds(chain, ids) {
2749
3124
  if (node.radicand) {
2750
3125
  collectNodeIds(node.radicand, ids);
2751
3126
  }
3127
+ if (node.overExpr) {
3128
+ collectNodeIds(node.overExpr, ids);
3129
+ }
3130
+ if (node.underExpr) {
3131
+ collectNodeIds(node.underExpr, ids);
3132
+ }
3133
+ if (node.baseExpr) {
3134
+ collectNodeIds(node.baseExpr, ids);
3135
+ }
2752
3136
  if (node.matrixRows) {
2753
3137
  for (const row of node.matrixRows) {
2754
3138
  for (const cell of row) {
@@ -2913,6 +3297,22 @@ function renderMatrixRowsArabic(node, options) {
2913
3297
  }
2914
3298
  return `\\begin{${envName}}${rows.join(" \\\\\n")}\\end{${envName}}`;
2915
3299
  }
3300
+ function renderAccentEnglish(command, accent, base, options) {
3301
+ const baseTex = base ? renderChainEnglish(base, options) : "";
3302
+ const accentTex = accent ? renderChainEnglish(accent, options) : "";
3303
+ if (accentTex === "") {
3304
+ return baseTex;
3305
+ }
3306
+ return `\\${command}{${accentTex}}{${baseTex}}`;
3307
+ }
3308
+ function renderAccentArabic(command, accent, base, options) {
3309
+ const baseTex = base ? renderChainArabic(base, options) : "";
3310
+ const accentTex = accent ? renderChainArabic(accent, options) : "";
3311
+ if (accentTex === "") {
3312
+ return baseTex;
3313
+ }
3314
+ return `\\${command}{${accentTex}}{${baseTex}}`;
3315
+ }
2916
3316
  function escapeText(s) {
2917
3317
  return s.replace(/\\/g, "\\textbackslash{}").replace(/[{}]/g, "\\$&");
2918
3318
  }
@@ -2942,6 +3342,19 @@ function renderNodeEnglish(node, options) {
2942
3342
  const body = `\\sqrt${optionalRootIndexEnglish(node, options)}{${renderChainEnglish(node.radicand, options)}}`;
2943
3343
  return `${body}${latinScripts(node, options)}`;
2944
3344
  }
3345
+ if (node.kind === "overset" && node.baseExpr) {
3346
+ const body = renderAccentEnglish("overset", node.overExpr, node.baseExpr, options);
3347
+ return `${body}${latinScripts(node, options)}`;
3348
+ }
3349
+ if (node.kind === "underset" && node.baseExpr) {
3350
+ const body = renderAccentEnglish("underset", node.underExpr, node.baseExpr, options);
3351
+ return `${body}${latinScripts(node, options)}`;
3352
+ }
3353
+ if (node.kind === "accent" && node.baseExpr) {
3354
+ const cmd = accentCommandSpec(node.expr)?.englishTex ?? `\\${node.expr}`;
3355
+ const body = `${cmd}{${renderChainEnglish(node.baseExpr, options)}}`;
3356
+ return `${body}${latinScripts(node, options)}`;
3357
+ }
2945
3358
  if (node.kind === "env") {
2946
3359
  return `${renderMatrixRowsEnglish(node, options)}${latinScripts(node, options)}`;
2947
3360
  }
@@ -2974,6 +3387,19 @@ function renderNodeArabic(node, options) {
2974
3387
  const content = `\\arabsqrt${optionalRootIndexArabic(node, options)}{${renderChainArabic(node.radicand, options)}}`;
2975
3388
  return arabicScripts(node, content, options);
2976
3389
  }
3390
+ if (node.kind === "overset" && node.baseExpr) {
3391
+ const content = renderAccentArabic("overset", node.overExpr, node.baseExpr, options);
3392
+ return arabicScripts(node, content, options);
3393
+ }
3394
+ if (node.kind === "underset" && node.baseExpr) {
3395
+ const content = renderAccentArabic("underset", node.underExpr, node.baseExpr, options);
3396
+ return arabicScripts(node, content, options);
3397
+ }
3398
+ if (node.kind === "accent" && node.baseExpr) {
3399
+ const cmd = accentCommandSpec(node.expr)?.arabicTex ?? `\\${node.expr}`;
3400
+ const content = `${cmd}{${renderChainArabic(node.baseExpr, options)}}`;
3401
+ return arabicScripts(node, content, options);
3402
+ }
2977
3403
  if (node.kind === "env") {
2978
3404
  return arabicScripts(node, renderMatrixRowsArabic(node, options), options);
2979
3405
  }
@@ -3030,6 +3456,35 @@ function collectCaretPositions(chain) {
3030
3456
  if (node.radicand) {
3031
3457
  walkChain(node.radicand);
3032
3458
  }
3459
+ if (node.kind === "overset") {
3460
+ if (node.overExpr) {
3461
+ walkChain(node.overExpr);
3462
+ }
3463
+ if (node.baseExpr) {
3464
+ walkChain(node.baseExpr);
3465
+ }
3466
+ } else if (node.kind === "underset") {
3467
+ if (node.baseExpr) {
3468
+ walkChain(node.baseExpr);
3469
+ }
3470
+ if (node.underExpr) {
3471
+ walkChain(node.underExpr);
3472
+ }
3473
+ } else if (node.kind === "accent") {
3474
+ if (node.baseExpr) {
3475
+ walkChain(node.baseExpr);
3476
+ }
3477
+ } else {
3478
+ if (node.overExpr) {
3479
+ walkChain(node.overExpr);
3480
+ }
3481
+ if (node.underExpr) {
3482
+ walkChain(node.underExpr);
3483
+ }
3484
+ if (node.baseExpr) {
3485
+ walkChain(node.baseExpr);
3486
+ }
3487
+ }
3033
3488
  if (node.matrixRows) {
3034
3489
  for (const row of node.matrixRows) {
3035
3490
  for (const cell of row) {
@@ -3163,6 +3618,42 @@ function findChainById(root, chainId) {
3163
3618
  return nested;
3164
3619
  }
3165
3620
  }
3621
+ if (node.overExpr) {
3622
+ if (node.overExpr.id === chainId) {
3623
+ return {
3624
+ chain: node.overExpr,
3625
+ relation: { kind: "overExpr", ownerNodeId: node.id, ownerChainId: root.id }
3626
+ };
3627
+ }
3628
+ const nested = findChainById(node.overExpr, chainId);
3629
+ if (nested) {
3630
+ return nested;
3631
+ }
3632
+ }
3633
+ if (node.underExpr) {
3634
+ if (node.underExpr.id === chainId) {
3635
+ return {
3636
+ chain: node.underExpr,
3637
+ relation: { kind: "underExpr", ownerNodeId: node.id, ownerChainId: root.id }
3638
+ };
3639
+ }
3640
+ const nested = findChainById(node.underExpr, chainId);
3641
+ if (nested) {
3642
+ return nested;
3643
+ }
3644
+ }
3645
+ if (node.baseExpr) {
3646
+ if (node.baseExpr.id === chainId) {
3647
+ return {
3648
+ chain: node.baseExpr,
3649
+ relation: { kind: "baseExpr", ownerNodeId: node.id, ownerChainId: root.id }
3650
+ };
3651
+ }
3652
+ const nested = findChainById(node.baseExpr, chainId);
3653
+ if (nested) {
3654
+ return nested;
3655
+ }
3656
+ }
3166
3657
  if (node.matrixRows) {
3167
3658
  for (let rowIndex = 0; rowIndex < node.matrixRows.length; rowIndex += 1) {
3168
3659
  const row = node.matrixRows[rowIndex];
@@ -3236,6 +3727,24 @@ function findNodeById(root, nodeId) {
3236
3727
  return nested;
3237
3728
  }
3238
3729
  }
3730
+ if (node.overExpr) {
3731
+ const nested = findNodeById(node.overExpr, nodeId);
3732
+ if (nested) {
3733
+ return nested;
3734
+ }
3735
+ }
3736
+ if (node.underExpr) {
3737
+ const nested = findNodeById(node.underExpr, nodeId);
3738
+ if (nested) {
3739
+ return nested;
3740
+ }
3741
+ }
3742
+ if (node.baseExpr) {
3743
+ const nested = findNodeById(node.baseExpr, nodeId);
3744
+ if (nested) {
3745
+ return nested;
3746
+ }
3747
+ }
3239
3748
  if (node.matrixRows) {
3240
3749
  for (const row of node.matrixRows) {
3241
3750
  for (const cell of row) {
@@ -3274,6 +3783,15 @@ function nodeChildChains(node) {
3274
3783
  if (node.radicand) {
3275
3784
  chains.push(node.radicand);
3276
3785
  }
3786
+ if (node.overExpr) {
3787
+ chains.push(node.overExpr);
3788
+ }
3789
+ if (node.underExpr) {
3790
+ chains.push(node.underExpr);
3791
+ }
3792
+ if (node.baseExpr) {
3793
+ chains.push(node.baseExpr);
3794
+ }
3277
3795
  if (node.matrixRows) {
3278
3796
  for (const row of node.matrixRows) {
3279
3797
  chains.push(...row);
@@ -3644,6 +4162,91 @@ function derivativeTemplateInitialCaret(englishFrac) {
3644
4162
  };
3645
4163
  }
3646
4164
 
4165
+ // src/editor/limitsTemplates.ts
4166
+ var LIMITS_SERIES_TEMPLATE_IDS = /* @__PURE__ */ new Set([
4167
+ "sum",
4168
+ "prod",
4169
+ "lim",
4170
+ "max",
4171
+ "min",
4172
+ "sup",
4173
+ "inf"
4174
+ ]);
4175
+ function isLimitsSeriesTemplateId(commandId) {
4176
+ return LIMITS_SERIES_TEMPLATE_IDS.has(commandId);
4177
+ }
4178
+ function syncChainIds2(english, arabic) {
4179
+ arabic.id = english.id;
4180
+ const limit = Math.min(english.nodes.length, arabic.nodes.length);
4181
+ for (let index = 0; index < limit; index += 1) {
4182
+ arabic.nodes[index].id = english.nodes[index].id;
4183
+ }
4184
+ }
4185
+ function syncOversetIds(english, arabic) {
4186
+ arabic.id = english.id;
4187
+ if (english.overExpr && arabic.overExpr) {
4188
+ syncChainIds2(english.overExpr, arabic.overExpr);
4189
+ }
4190
+ if (english.baseExpr && arabic.baseExpr) {
4191
+ syncChainIds2(english.baseExpr, arabic.baseExpr);
4192
+ }
4193
+ }
4194
+ function syncUndersetIds(english, arabic) {
4195
+ arabic.id = english.id;
4196
+ if (english.underExpr && arabic.underExpr) {
4197
+ syncChainIds2(english.underExpr, arabic.underExpr);
4198
+ }
4199
+ if (english.baseExpr && arabic.baseExpr) {
4200
+ syncChainIds2(english.baseExpr, arabic.baseExpr);
4201
+ }
4202
+ }
4203
+ function buildLimitsSeriesTemplate(commandId) {
4204
+ if (!isLimitsSeriesTemplateId(commandId)) {
4205
+ throw new Error(`BuTeX: unsupported limits-series template id: ${commandId}`);
4206
+ }
4207
+ const englishOp = createAtomicCommandNode(commandId);
4208
+ const arabicOp = createAtomicCommandNode(commandId);
4209
+ arabicOp.id = englishOp.id;
4210
+ const englishOverset = createOversetNode();
4211
+ const arabicOverset = createOversetNode();
4212
+ syncOversetIds(englishOverset, arabicOverset);
4213
+ englishOverset.baseExpr = createEditorChain([englishOp]);
4214
+ arabicOverset.baseExpr = createEditorChain([arabicOp]);
4215
+ syncChainIds2(englishOverset.baseExpr, arabicOverset.baseExpr);
4216
+ const englishUnderset = createUndersetNode();
4217
+ const arabicUnderset = createUndersetNode();
4218
+ syncUndersetIds(englishUnderset, arabicUnderset);
4219
+ englishUnderset.baseExpr = createEditorChain([englishOverset]);
4220
+ arabicUnderset.baseExpr = createEditorChain([arabicOverset]);
4221
+ syncChainIds2(englishUnderset.baseExpr, arabicUnderset.baseExpr);
4222
+ return { english: englishUnderset, arabic: arabicUnderset };
4223
+ }
4224
+ function buildAccentPairTemplate() {
4225
+ const englishOverset = createOversetNode();
4226
+ const arabicOverset = createOversetNode();
4227
+ syncOversetIds(englishOverset, arabicOverset);
4228
+ const englishUnderset = createUndersetNode();
4229
+ const arabicUnderset = createUndersetNode();
4230
+ syncUndersetIds(englishUnderset, arabicUnderset);
4231
+ englishUnderset.baseExpr = createEditorChain([englishOverset]);
4232
+ arabicUnderset.baseExpr = createEditorChain([arabicOverset]);
4233
+ syncChainIds2(englishUnderset.baseExpr, arabicUnderset.baseExpr);
4234
+ return { english: englishUnderset, arabic: arabicUnderset };
4235
+ }
4236
+ function accentPairTemplateInitialCaret(englishUnderset) {
4237
+ const overset = englishUnderset.baseExpr?.nodes[0];
4238
+ return {
4239
+ chainId: overset?.baseExpr?.id ?? englishUnderset.underExpr?.id ?? "",
4240
+ index: 0
4241
+ };
4242
+ }
4243
+ function limitsSeriesTemplateInitialCaret(englishUnderset) {
4244
+ return {
4245
+ chainId: englishUnderset.underExpr?.id ?? englishUnderset.baseExpr?.id ?? "",
4246
+ index: 0
4247
+ };
4248
+ }
4249
+
3647
4250
  // src/editor/state.ts
3648
4251
  function ensureSyncEntry(session, nodeId) {
3649
4252
  if (!session.sync[nodeId]) {
@@ -3677,7 +4280,7 @@ function syncSelectionToCaret(session) {
3677
4280
  session.selectedNodeId = located.relation.ownerNodeId;
3678
4281
  return;
3679
4282
  }
3680
- if (located.relation.kind === "inner" || located.relation.kind === "numerator" || located.relation.kind === "denominator" || located.relation.kind === "radicand" || located.relation.kind === "rootIndex" || located.relation.kind === "matrixCell") {
4283
+ if (located.relation.kind === "inner" || located.relation.kind === "numerator" || located.relation.kind === "denominator" || located.relation.kind === "radicand" || located.relation.kind === "rootIndex" || located.relation.kind === "overExpr" || located.relation.kind === "underExpr" || located.relation.kind === "baseExpr" || located.relation.kind === "matrixCell") {
3681
4284
  session.selectedNodeId = located.relation.ownerNodeId;
3682
4285
  return;
3683
4286
  }
@@ -4034,6 +4637,106 @@ function moveCaretVertical(session, direction) {
4034
4637
  appendDebug(next, "moveCaretVertical", "sqrt-radicand-down-exit");
4035
4638
  return next;
4036
4639
  }
4640
+ if (located.relation.kind === "overExpr" && ownerLocated && ownerNode && ownerNode.baseExpr) {
4641
+ if (direction === "down") {
4642
+ next.caret = {
4643
+ chainId: ownerNode.baseExpr.id,
4644
+ index: ownerNode.baseExpr.nodes.length
4645
+ };
4646
+ next.selectedStructureNodeId = null;
4647
+ syncSelectionToCaret(next);
4648
+ appendDebug(next, "moveCaretVertical", "overset-over->base");
4649
+ return next;
4650
+ }
4651
+ next.caret = {
4652
+ chainId: ownerLocated.chain.id,
4653
+ index: ownerLocated.index
4654
+ };
4655
+ next.selectedStructureNodeId = null;
4656
+ syncSelectionToCaret(next);
4657
+ appendDebug(next, "moveCaretVertical", "overset-over-up-exit");
4658
+ return next;
4659
+ }
4660
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "overset" && ownerNode.overExpr) {
4661
+ if (direction === "up") {
4662
+ next.caret = {
4663
+ chainId: ownerNode.overExpr.id,
4664
+ index: ownerNode.overExpr.nodes.length
4665
+ };
4666
+ next.selectedStructureNodeId = null;
4667
+ syncSelectionToCaret(next);
4668
+ appendDebug(next, "moveCaretVertical", "overset-base->over");
4669
+ return next;
4670
+ }
4671
+ next.caret = {
4672
+ chainId: ownerLocated.chain.id,
4673
+ index: ownerLocated.index + 1
4674
+ };
4675
+ next.selectedStructureNodeId = null;
4676
+ syncSelectionToCaret(next);
4677
+ appendDebug(next, "moveCaretVertical", "overset-base-down-exit");
4678
+ return next;
4679
+ }
4680
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "underset" && ownerNode.underExpr) {
4681
+ if (direction === "down") {
4682
+ next.caret = {
4683
+ chainId: ownerNode.underExpr.id,
4684
+ index: ownerNode.underExpr.nodes.length
4685
+ };
4686
+ next.selectedStructureNodeId = null;
4687
+ syncSelectionToCaret(next);
4688
+ appendDebug(next, "moveCaretVertical", "underset-base->under");
4689
+ return next;
4690
+ }
4691
+ next.caret = {
4692
+ chainId: ownerLocated.chain.id,
4693
+ index: ownerLocated.index
4694
+ };
4695
+ next.selectedStructureNodeId = null;
4696
+ syncSelectionToCaret(next);
4697
+ appendDebug(next, "moveCaretVertical", "underset-base-up-exit");
4698
+ return next;
4699
+ }
4700
+ if (located.relation.kind === "underExpr" && ownerLocated && ownerNode && ownerNode.baseExpr) {
4701
+ if (direction === "up") {
4702
+ next.caret = {
4703
+ chainId: ownerNode.baseExpr.id,
4704
+ index: ownerNode.baseExpr.nodes.length
4705
+ };
4706
+ next.selectedStructureNodeId = null;
4707
+ syncSelectionToCaret(next);
4708
+ appendDebug(next, "moveCaretVertical", "underset-under->base");
4709
+ return next;
4710
+ }
4711
+ next.caret = {
4712
+ chainId: ownerLocated.chain.id,
4713
+ index: ownerLocated.index + 1
4714
+ };
4715
+ next.selectedStructureNodeId = null;
4716
+ syncSelectionToCaret(next);
4717
+ appendDebug(next, "moveCaretVertical", "underset-under-down-exit");
4718
+ return next;
4719
+ }
4720
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "accent") {
4721
+ if (direction === "up") {
4722
+ next.caret = {
4723
+ chainId: ownerLocated.chain.id,
4724
+ index: ownerLocated.index
4725
+ };
4726
+ next.selectedStructureNodeId = null;
4727
+ syncSelectionToCaret(next);
4728
+ appendDebug(next, "moveCaretVertical", "accent-base-up-exit");
4729
+ return next;
4730
+ }
4731
+ next.caret = {
4732
+ chainId: ownerLocated.chain.id,
4733
+ index: ownerLocated.index + 1
4734
+ };
4735
+ next.selectedStructureNodeId = null;
4736
+ syncSelectionToCaret(next);
4737
+ appendDebug(next, "moveCaretVertical", "accent-base-down-exit");
4738
+ return next;
4739
+ }
4037
4740
  if (located.relation.kind === "matrixCell" && ownerLocated && ownerNode?.matrixRows) {
4038
4741
  const rowIndex = located.relation.rowIndex ?? 0;
4039
4742
  const columnIndex = located.relation.columnIndex ?? 0;
@@ -4411,6 +5114,119 @@ function insertSqrt(session) {
4411
5114
  appendDebug(next, "insertSqrt", "");
4412
5115
  return next;
4413
5116
  }
5117
+ function insertOverset(session) {
5118
+ const base = replaceSelectionFirst(session);
5119
+ const next = cloneEditorSession(base);
5120
+ const englishNode = createOversetNode();
5121
+ const arabicNode = createOversetNode();
5122
+ arabicNode.id = englishNode.id;
5123
+ if (arabicNode.overExpr && englishNode.overExpr) {
5124
+ arabicNode.overExpr.id = englishNode.overExpr.id;
5125
+ }
5126
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
5127
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
5128
+ }
5129
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
5130
+ next.caret = {
5131
+ chainId: englishNode.overExpr ? englishNode.overExpr.id : next.caret.chainId,
5132
+ index: 0
5133
+ };
5134
+ next.selectedStructureNodeId = null;
5135
+ syncSelectionToCaret(next);
5136
+ appendDebug(next, "insertOverset", "");
5137
+ return next;
5138
+ }
5139
+ function insertUnderset(session) {
5140
+ const base = replaceSelectionFirst(session);
5141
+ const next = cloneEditorSession(base);
5142
+ const englishNode = createUndersetNode();
5143
+ const arabicNode = createUndersetNode();
5144
+ arabicNode.id = englishNode.id;
5145
+ if (arabicNode.underExpr && englishNode.underExpr) {
5146
+ arabicNode.underExpr.id = englishNode.underExpr.id;
5147
+ }
5148
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
5149
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
5150
+ }
5151
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
5152
+ next.caret = {
5153
+ chainId: englishNode.underExpr ? englishNode.underExpr.id : next.caret.chainId,
5154
+ index: 0
5155
+ };
5156
+ next.selectedStructureNodeId = null;
5157
+ syncSelectionToCaret(next);
5158
+ appendDebug(next, "insertUnderset", "");
5159
+ return next;
5160
+ }
5161
+ function insertLimitsSeriesTemplate(session, commandId) {
5162
+ const base = replaceSelectionFirst(session);
5163
+ const next = cloneEditorSession(base);
5164
+ const { english, arabic } = buildLimitsSeriesTemplate(commandId);
5165
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, english, arabic);
5166
+ syncSubtreeRecursive(next, english, arabic);
5167
+ next.caret = limitsSeriesTemplateInitialCaret(english);
5168
+ next.selectedStructureNodeId = null;
5169
+ syncSelectionToCaret(next);
5170
+ appendDebug(next, "insertLimitsSeriesTemplate", commandId);
5171
+ return next;
5172
+ }
5173
+ function insertAccentPair(session) {
5174
+ const base = replaceSelectionFirst(session);
5175
+ const next = cloneEditorSession(base);
5176
+ const { english, arabic } = buildAccentPairTemplate();
5177
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, english, arabic);
5178
+ syncSubtreeRecursive(next, english, arabic);
5179
+ next.caret = accentPairTemplateInitialCaret(english);
5180
+ next.selectedStructureNodeId = null;
5181
+ syncSelectionToCaret(next);
5182
+ appendDebug(next, "insertAccentPair", "");
5183
+ return next;
5184
+ }
5185
+ function insertAccent(session, accentId) {
5186
+ const next = cloneEditorSession(session);
5187
+ const englishNode = createAccentNode(accentId);
5188
+ const arabicNode = createAccentNode(accentId);
5189
+ arabicNode.id = englishNode.id;
5190
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
5191
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
5192
+ }
5193
+ if (isSelectionActive(next.selection) && next.selection) {
5194
+ const sel = next.selection;
5195
+ const { start, end } = normalizeSelection(sel);
5196
+ const englishLocated = findChainById(next.englishTree, sel.chainId);
5197
+ const arabicLocated = findChainById(next.arabicTree, sel.chainId);
5198
+ if (englishLocated && arabicLocated && end > start) {
5199
+ const count = end - start;
5200
+ const englishWrapped = englishLocated.chain.nodes.splice(start, count);
5201
+ const arabicWrapped = arabicLocated.chain.nodes.splice(start, count);
5202
+ englishNode.baseExpr.nodes = englishWrapped;
5203
+ arabicNode.baseExpr.nodes = arabicWrapped;
5204
+ englishLocated.chain.nodes.splice(start, 0, englishNode);
5205
+ arabicLocated.chain.nodes.splice(start, 0, arabicNode);
5206
+ syncSubtreeRecursive(next, englishNode, arabicNode);
5207
+ next.caret = {
5208
+ chainId: englishNode.baseExpr.id,
5209
+ index: englishWrapped.length
5210
+ };
5211
+ next.selection = null;
5212
+ next.selectedStructureNodeId = null;
5213
+ syncSelectionToCaret(next);
5214
+ appendDebug(next, "insertAccent", `${accentId}:wrap`);
5215
+ return next;
5216
+ }
5217
+ }
5218
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
5219
+ syncSubtreeRecursive(next, englishNode, arabicNode);
5220
+ next.caret = {
5221
+ chainId: englishNode.baseExpr ? englishNode.baseExpr.id : next.caret.chainId,
5222
+ index: 0
5223
+ };
5224
+ next.selection = null;
5225
+ next.selectedStructureNodeId = null;
5226
+ syncSelectionToCaret(next);
5227
+ appendDebug(next, "insertAccent", `${accentId}:empty`);
5228
+ return next;
5229
+ }
4414
5230
  function insertMatrixEnv(session, style, rows, columns) {
4415
5231
  return insertGridEnv(session, style, rows, columns);
4416
5232
  }
@@ -4658,7 +5474,7 @@ function deleteBackward(session) {
4658
5474
  if (!previousNode) {
4659
5475
  return session;
4660
5476
  }
4661
- if ((previousNode.kind === "delimiter" || previousNode.kind === "frac" || previousNode.kind === "sqrt" || previousNode.kind === "env") && next.selectedStructureNodeId !== previousNode.id) {
5477
+ if ((previousNode.kind === "delimiter" || previousNode.kind === "frac" || previousNode.kind === "sqrt" || previousNode.kind === "overset" || previousNode.kind === "underset" || previousNode.kind === "accent" || previousNode.kind === "env") && next.selectedStructureNodeId !== previousNode.id) {
4662
5478
  next.selectedStructureNodeId = previousNode.id;
4663
5479
  next.selectedNodeId = previousNode.id;
4664
5480
  appendDebug(next, "deleteBackward", "selected structure");
@@ -4953,6 +5769,15 @@ function buildNodeBody(node, buildChain, side, digitForm = "western", uiLocale =
4953
5769
  if (node.kind === "sqrt") {
4954
5770
  return buildSqrtNodeBody(node, buildChain, side);
4955
5771
  }
5772
+ if (node.kind === "overset") {
5773
+ return buildOversetNodeBody(node, buildChain);
5774
+ }
5775
+ if (node.kind === "underset") {
5776
+ return buildUndersetNodeBody(node, buildChain);
5777
+ }
5778
+ if (node.kind === "accent") {
5779
+ return buildAccentNodeBody(node, buildChain);
5780
+ }
4956
5781
  if (node.kind === "env") {
4957
5782
  return buildMatrixEnvNodeBody(node, buildChain, side);
4958
5783
  }
@@ -5661,6 +6486,26 @@ function createEditorRuntime(options) {
5661
6486
  applyStructural((prev) => insertSqrt(prev));
5662
6487
  surfaceEl.focus();
5663
6488
  },
6489
+ insertOverset: () => {
6490
+ applyStructural((prev) => insertOverset(prev));
6491
+ surfaceEl.focus();
6492
+ },
6493
+ insertUnderset: () => {
6494
+ applyStructural((prev) => insertUnderset(prev));
6495
+ surfaceEl.focus();
6496
+ },
6497
+ insertLimitsSeriesTemplate: (commandId) => {
6498
+ applyStructural((prev) => insertLimitsSeriesTemplate(prev, commandId));
6499
+ surfaceEl.focus();
6500
+ },
6501
+ insertAccentPair: () => {
6502
+ applyStructural((prev) => insertAccentPair(prev));
6503
+ surfaceEl.focus();
6504
+ },
6505
+ insertAccent: (accentId) => {
6506
+ applyStructural((prev) => insertAccent(prev, accentId));
6507
+ surfaceEl.focus();
6508
+ },
5664
6509
  insertAtomicCommand: (commandId) => {
5665
6510
  applyStructural((prev) => insertAtomicCommand(prev, commandId));
5666
6511
  surfaceEl.focus();