@drghaliasri/butex 5.5.5 → 5.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/document.js +36 -0
- package/dist/document.js.map +1 -1
- package/dist/document.mjs +36 -0
- package/dist/document.mjs.map +1 -1
- package/dist/document2.d.mts +4 -2
- package/dist/document2.d.ts +4 -2
- package/dist/document2.js +173 -20
- package/dist/document2.js.map +1 -1
- package/dist/document2.mjs +173 -20
- package/dist/document2.mjs.map +1 -1
- package/dist/index.d.mts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.global.js +79 -14
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +79 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +79 -14
- package/dist/index.mjs.map +1 -1
- package/dist/react-document.js +254 -7
- package/dist/react-document.js.map +1 -1
- package/dist/react-document.mjs +254 -7
- package/dist/react-document.mjs.map +1 -1
- package/dist/react-document2.d.mts +5 -3
- package/dist/react-document2.d.ts +5 -3
- package/dist/react-document2.js +375 -33
- package/dist/react-document2.js.map +1 -1
- package/dist/react-document2.mjs +375 -33
- package/dist/react-document2.mjs.map +1 -1
- package/dist/react.d.mts +35 -0
- package/dist/react.d.ts +35 -0
- package/dist/react.js +1277 -7
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +1277 -7
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -146,6 +146,81 @@ function cloneEditorSession(session) {
|
|
|
146
146
|
debugLog: session.debugLog.slice()
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
+
function collectNodeIds(chain, ids) {
|
|
150
|
+
for (const node of chain.nodes) {
|
|
151
|
+
ids.push(node.id);
|
|
152
|
+
if (node.superscript) {
|
|
153
|
+
collectNodeIds(node.superscript, ids);
|
|
154
|
+
}
|
|
155
|
+
if (node.subscript) {
|
|
156
|
+
collectNodeIds(node.subscript, ids);
|
|
157
|
+
}
|
|
158
|
+
if (node.innerExpr) {
|
|
159
|
+
collectNodeIds(node.innerExpr, ids);
|
|
160
|
+
}
|
|
161
|
+
if (node.numerator) {
|
|
162
|
+
collectNodeIds(node.numerator, ids);
|
|
163
|
+
}
|
|
164
|
+
if (node.denominator) {
|
|
165
|
+
collectNodeIds(node.denominator, ids);
|
|
166
|
+
}
|
|
167
|
+
if (node.rootIndex) {
|
|
168
|
+
collectNodeIds(node.rootIndex, ids);
|
|
169
|
+
}
|
|
170
|
+
if (node.radicand) {
|
|
171
|
+
collectNodeIds(node.radicand, ids);
|
|
172
|
+
}
|
|
173
|
+
if (node.overExpr) {
|
|
174
|
+
collectNodeIds(node.overExpr, ids);
|
|
175
|
+
}
|
|
176
|
+
if (node.underExpr) {
|
|
177
|
+
collectNodeIds(node.underExpr, ids);
|
|
178
|
+
}
|
|
179
|
+
if (node.baseExpr) {
|
|
180
|
+
collectNodeIds(node.baseExpr, ids);
|
|
181
|
+
}
|
|
182
|
+
if (node.matrixRows) {
|
|
183
|
+
for (const row of node.matrixRows) {
|
|
184
|
+
for (const cell of row) {
|
|
185
|
+
collectNodeIds(cell, ids);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function buildInitialSyncMap(englishTree, arabicTree) {
|
|
192
|
+
const englishIds = [];
|
|
193
|
+
const arabicIds = [];
|
|
194
|
+
collectNodeIds(englishTree, englishIds);
|
|
195
|
+
collectNodeIds(arabicTree, arabicIds);
|
|
196
|
+
const all = /* @__PURE__ */ new Set([...englishIds, ...arabicIds]);
|
|
197
|
+
const sync = {};
|
|
198
|
+
for (const nodeId of all) {
|
|
199
|
+
sync[nodeId] = { expr: "synced" };
|
|
200
|
+
}
|
|
201
|
+
return sync;
|
|
202
|
+
}
|
|
203
|
+
function createEditorSession(englishTree, arabicTree, activeSide = "arabic") {
|
|
204
|
+
return {
|
|
205
|
+
englishTree,
|
|
206
|
+
arabicTree,
|
|
207
|
+
activeSide,
|
|
208
|
+
splitLeafTyping: false,
|
|
209
|
+
forceSplitNextLeaf: false,
|
|
210
|
+
arabicReverseNumberTyping: true,
|
|
211
|
+
currentCharacterFont: "default",
|
|
212
|
+
currentDigitForm: "western",
|
|
213
|
+
caret: {
|
|
214
|
+
chainId: englishTree.id,
|
|
215
|
+
index: 0
|
|
216
|
+
},
|
|
217
|
+
selection: null,
|
|
218
|
+
selectedNodeId: null,
|
|
219
|
+
selectedStructureNodeId: null,
|
|
220
|
+
sync: buildInitialSyncMap(englishTree, arabicTree),
|
|
221
|
+
debugLog: []
|
|
222
|
+
};
|
|
223
|
+
}
|
|
149
224
|
|
|
150
225
|
// src/editor/accentCommands.ts
|
|
151
226
|
var ACCENT_COMMANDS = {
|
|
@@ -284,6 +359,20 @@ function accentCommandSpec(id) {
|
|
|
284
359
|
function accentCommandsList() {
|
|
285
360
|
return Object.values(ACCENT_COMMANDS);
|
|
286
361
|
}
|
|
362
|
+
function accentCommandIdFromTex(tex) {
|
|
363
|
+
const normalized = tex.startsWith("\\") ? tex : `\\${tex}`;
|
|
364
|
+
for (const spec of Object.values(ACCENT_COMMANDS)) {
|
|
365
|
+
if (spec.englishTex === normalized) {
|
|
366
|
+
return spec.id;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
for (const spec of Object.values(ACCENT_COMMANDS)) {
|
|
370
|
+
if (spec.arabicTex === normalized) {
|
|
371
|
+
return spec.id;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
287
376
|
|
|
288
377
|
// src/editor/atomicCommands.ts
|
|
289
378
|
var ATOMIC_COMMANDS = {
|
|
@@ -706,6 +795,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
706
795
|
category: "operators1",
|
|
707
796
|
Tex: "\\neq",
|
|
708
797
|
mirror: true,
|
|
798
|
+
compileMirror: true,
|
|
709
799
|
Label: "\u2260",
|
|
710
800
|
title: "\u0644\u0627 \u064A\u0633\u0627\u0648\u064A",
|
|
711
801
|
svg_path: null
|
|
@@ -745,6 +835,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
745
835
|
Tex: "\\leq",
|
|
746
836
|
mirror: true,
|
|
747
837
|
displayMirror: false,
|
|
838
|
+
compileMirror: true,
|
|
748
839
|
Label: "\u2264",
|
|
749
840
|
title: "\u0623\u0635\u063A\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
|
|
750
841
|
svg_path: null
|
|
@@ -755,6 +846,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
755
846
|
Tex: "\\geq",
|
|
756
847
|
mirror: true,
|
|
757
848
|
displayMirror: false,
|
|
849
|
+
compileMirror: true,
|
|
758
850
|
Label: "\u2265",
|
|
759
851
|
title: "\u0623\u0643\u0628\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
|
|
760
852
|
svg_path: null
|
|
@@ -765,6 +857,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
765
857
|
Tex: "\\coloneqq",
|
|
766
858
|
mirror: true,
|
|
767
859
|
displayMirror: false,
|
|
860
|
+
compileMirror: true,
|
|
768
861
|
Label: "\u2254",
|
|
769
862
|
title: "\u064A\u0639\u0631\u0641 \u0628\u0623\u0646\u0647 \u064A\u0633\u0627\u0648\u064A",
|
|
770
863
|
svg_path: null
|
|
@@ -775,6 +868,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
775
868
|
Tex: "\\eqqcolon",
|
|
776
869
|
mirror: true,
|
|
777
870
|
displayMirror: false,
|
|
871
|
+
compileMirror: true,
|
|
778
872
|
Label: "\u2255",
|
|
779
873
|
title: "\u064A\u0633\u0627\u0648\u064A \u0628\u0627\u0644\u062A\u0639\u0631\u064A\u0641",
|
|
780
874
|
svg_path: null
|
|
@@ -786,6 +880,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
786
880
|
Tex: "\\propto",
|
|
787
881
|
mirror: true,
|
|
788
882
|
displayMirror: false,
|
|
883
|
+
compileMirror: true,
|
|
789
884
|
Label: "\u221D",
|
|
790
885
|
title: "\u064A\u062A\u0646\u0627\u0633\u0628 \u0645\u0639",
|
|
791
886
|
svg_path: null
|
|
@@ -796,6 +891,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
796
891
|
Tex: "\\in",
|
|
797
892
|
mirror: true,
|
|
798
893
|
displayMirror: false,
|
|
894
|
+
compileMirror: true,
|
|
799
895
|
Label: "\u2208",
|
|
800
896
|
title: "\u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
|
|
801
897
|
svg_path: null
|
|
@@ -816,6 +912,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
816
912
|
Tex: "\\subset",
|
|
817
913
|
mirror: true,
|
|
818
914
|
displayMirror: false,
|
|
915
|
+
compileMirror: true,
|
|
819
916
|
Label: "\u2282",
|
|
820
917
|
title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0645\u0646",
|
|
821
918
|
svg_path: null
|
|
@@ -826,6 +923,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
826
923
|
Tex: "\\supset",
|
|
827
924
|
mirror: true,
|
|
828
925
|
displayMirror: false,
|
|
926
|
+
compileMirror: true,
|
|
829
927
|
Label: "\u2283",
|
|
830
928
|
title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0644\u0640",
|
|
831
929
|
svg_path: null
|
|
@@ -836,6 +934,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
836
934
|
Tex: "\\subseteq",
|
|
837
935
|
mirror: true,
|
|
838
936
|
displayMirror: false,
|
|
937
|
+
compileMirror: true,
|
|
839
938
|
Label: "\u2286",
|
|
840
939
|
title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
|
|
841
940
|
svg_path: null
|
|
@@ -846,6 +945,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
846
945
|
Tex: "\\supseteq",
|
|
847
946
|
mirror: true,
|
|
848
947
|
displayMirror: false,
|
|
948
|
+
compileMirror: true,
|
|
849
949
|
Label: "\u2287",
|
|
850
950
|
title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
|
|
851
951
|
svg_path: null
|
|
@@ -886,6 +986,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
886
986
|
Tex: "\\nsubseteq",
|
|
887
987
|
mirror: true,
|
|
888
988
|
displayMirror: false,
|
|
989
|
+
compileMirror: true,
|
|
889
990
|
Label: "\u2288",
|
|
890
991
|
title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
|
|
891
992
|
svg_path: null
|
|
@@ -896,6 +997,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
896
997
|
Tex: "\\nsupseteq",
|
|
897
998
|
mirror: true,
|
|
898
999
|
displayMirror: false,
|
|
1000
|
+
compileMirror: true,
|
|
899
1001
|
Label: "\u2289",
|
|
900
1002
|
title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
|
|
901
1003
|
svg_path: null
|
|
@@ -943,6 +1045,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
943
1045
|
Tex: "\\ddots",
|
|
944
1046
|
mirror: true,
|
|
945
1047
|
displayMirror: false,
|
|
1048
|
+
compileMirror: true,
|
|
946
1049
|
Label: "\u22F1",
|
|
947
1050
|
title: "\u0646\u0642\u0627\u0637 \u0642\u0637\u0631\u064A\u0629",
|
|
948
1051
|
svg_path: null
|
|
@@ -962,6 +1065,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
962
1065
|
category: "operators3",
|
|
963
1066
|
Tex: "\\implies",
|
|
964
1067
|
mirror: true,
|
|
1068
|
+
compileMirror: true,
|
|
965
1069
|
Label: "\u21D2",
|
|
966
1070
|
title: "\u064A\u0633\u062A\u0644\u0632\u0645",
|
|
967
1071
|
svg_path: null
|
|
@@ -971,6 +1075,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
971
1075
|
category: "operators3",
|
|
972
1076
|
Tex: "\\impliedby",
|
|
973
1077
|
mirror: true,
|
|
1078
|
+
compileMirror: true,
|
|
974
1079
|
Label: "\u21D0",
|
|
975
1080
|
title: "\u0645\u0633\u062A\u0644\u0632\u0645 \u0645\u0646",
|
|
976
1081
|
svg_path: null
|
|
@@ -989,6 +1094,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
989
1094
|
category: "operators3",
|
|
990
1095
|
Tex: "\\Longrightarrow",
|
|
991
1096
|
mirror: true,
|
|
1097
|
+
compileMirror: true,
|
|
992
1098
|
Label: "\u27F9",
|
|
993
1099
|
title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0637\u0648\u064A\u0644 \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
|
|
994
1100
|
svg_path: null
|
|
@@ -998,6 +1104,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
998
1104
|
category: "operators3",
|
|
999
1105
|
Tex: "\\Longleftarrow",
|
|
1000
1106
|
mirror: true,
|
|
1107
|
+
compileMirror: true,
|
|
1001
1108
|
Label: "\u27F8",
|
|
1002
1109
|
title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0637\u0648\u064A\u0644 \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
|
|
1003
1110
|
svg_path: null
|
|
@@ -1007,6 +1114,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1007
1114
|
category: "operators3",
|
|
1008
1115
|
Tex: "\\to",
|
|
1009
1116
|
mirror: true,
|
|
1117
|
+
compileMirror: true,
|
|
1010
1118
|
Label: "\u2192",
|
|
1011
1119
|
title: "\u064A\u0624\u0648\u0644 \u0625\u0644\u0649",
|
|
1012
1120
|
svg_path: null
|
|
@@ -1016,6 +1124,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1016
1124
|
category: "operators3",
|
|
1017
1125
|
Tex: "\\rightleftharpoons",
|
|
1018
1126
|
mirror: true,
|
|
1127
|
+
compileMirror: true,
|
|
1019
1128
|
Label: "\u21CC",
|
|
1020
1129
|
title: "\u0627\u062A\u0632\u0627\u0646",
|
|
1021
1130
|
svg_path: null
|
|
@@ -1025,6 +1134,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1025
1134
|
category: "operators3",
|
|
1026
1135
|
Tex: "\\leftarrow",
|
|
1027
1136
|
mirror: true,
|
|
1137
|
+
compileMirror: true,
|
|
1028
1138
|
Label: "\u2190",
|
|
1029
1139
|
title: "\u0633\u0647\u0645 \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
|
|
1030
1140
|
svg_path: null
|
|
@@ -1034,6 +1144,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1034
1144
|
category: "operators3",
|
|
1035
1145
|
Tex: "\\rightarrow",
|
|
1036
1146
|
mirror: true,
|
|
1147
|
+
compileMirror: true,
|
|
1037
1148
|
Label: "\u2192",
|
|
1038
1149
|
title: "\u0633\u0647\u0645 \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
|
|
1039
1150
|
svg_path: null
|
|
@@ -1043,6 +1154,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1043
1154
|
category: "operators3",
|
|
1044
1155
|
Tex: "\\Leftarrow",
|
|
1045
1156
|
mirror: true,
|
|
1157
|
+
compileMirror: true,
|
|
1046
1158
|
Label: "\u21D0",
|
|
1047
1159
|
title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
|
|
1048
1160
|
svg_path: null
|
|
@@ -1052,6 +1164,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1052
1164
|
category: "operators3",
|
|
1053
1165
|
Tex: "\\Rightarrow",
|
|
1054
1166
|
mirror: true,
|
|
1167
|
+
compileMirror: true,
|
|
1055
1168
|
Label: "\u21D2",
|
|
1056
1169
|
title: "\u0633\u0647\u0645 \u0645\u0632\u062F\u0648\u062C \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
|
|
1057
1170
|
svg_path: null
|
|
@@ -1061,6 +1174,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1061
1174
|
category: "operators3",
|
|
1062
1175
|
Tex: "\\leftharpoonup",
|
|
1063
1176
|
mirror: true,
|
|
1177
|
+
compileMirror: true,
|
|
1064
1178
|
Label: "\u21BC",
|
|
1065
1179
|
title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
|
|
1066
1180
|
svg_path: null
|
|
@@ -1070,6 +1184,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1070
1184
|
category: "operators3",
|
|
1071
1185
|
Tex: "\\rightharpoonup",
|
|
1072
1186
|
mirror: true,
|
|
1187
|
+
compileMirror: true,
|
|
1073
1188
|
Label: "\u21C0",
|
|
1074
1189
|
title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
|
|
1075
1190
|
svg_path: null
|
|
@@ -1079,6 +1194,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1079
1194
|
category: "operators3",
|
|
1080
1195
|
Tex: "\\leftharpoondown",
|
|
1081
1196
|
mirror: true,
|
|
1197
|
+
compileMirror: true,
|
|
1082
1198
|
Label: "\u21BD",
|
|
1083
1199
|
title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0633\u0641\u0644\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631",
|
|
1084
1200
|
svg_path: null
|
|
@@ -1088,6 +1204,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1088
1204
|
category: "operators3",
|
|
1089
1205
|
Tex: "\\rightharpoondown",
|
|
1090
1206
|
mirror: true,
|
|
1207
|
+
compileMirror: true,
|
|
1091
1208
|
Label: "\u21C1",
|
|
1092
1209
|
title: "\u0633\u0647\u0645 \u062E\u0637\u0627\u0641\u064A \u0633\u0641\u0644\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646",
|
|
1093
1210
|
svg_path: null
|
|
@@ -1098,6 +1215,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1098
1215
|
category: "integrals",
|
|
1099
1216
|
Tex: "\\int",
|
|
1100
1217
|
mirror: true,
|
|
1218
|
+
compileMirror: true,
|
|
1101
1219
|
Label: "\u222B",
|
|
1102
1220
|
title: "\u062A\u0643\u0627\u0645\u0644",
|
|
1103
1221
|
svg_path: null
|
|
@@ -1108,6 +1226,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1108
1226
|
Tex: "\\iint",
|
|
1109
1227
|
mirror: true,
|
|
1110
1228
|
displayMirror: false,
|
|
1229
|
+
compileMirror: true,
|
|
1111
1230
|
Label: "\u222C",
|
|
1112
1231
|
title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u0632\u062F\u0648\u062C",
|
|
1113
1232
|
svg_path: null
|
|
@@ -1118,6 +1237,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1118
1237
|
Tex: "\\iiint",
|
|
1119
1238
|
mirror: true,
|
|
1120
1239
|
displayMirror: false,
|
|
1240
|
+
compileMirror: true,
|
|
1121
1241
|
Label: "\u222D",
|
|
1122
1242
|
title: "\u062A\u0643\u0627\u0645\u0644 \u062B\u0644\u0627\u062B\u064A",
|
|
1123
1243
|
svg_path: null
|
|
@@ -1128,6 +1248,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1128
1248
|
Tex: "\\iiiint",
|
|
1129
1249
|
mirror: true,
|
|
1130
1250
|
displayMirror: false,
|
|
1251
|
+
compileMirror: true,
|
|
1131
1252
|
Label: "\u2A0C",
|
|
1132
1253
|
title: "\u062A\u0643\u0627\u0645\u0644 \u0631\u0628\u0627\u0639\u064A",
|
|
1133
1254
|
svg_path: null
|
|
@@ -1138,6 +1259,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1138
1259
|
Tex: "\\oint",
|
|
1139
1260
|
mirror: true,
|
|
1140
1261
|
displayMirror: false,
|
|
1262
|
+
compileMirror: true,
|
|
1141
1263
|
Label: "\u222E",
|
|
1142
1264
|
title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u063A\u0644\u0642",
|
|
1143
1265
|
svg_path: null
|
|
@@ -1148,6 +1270,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1148
1270
|
Tex: "\\oiint",
|
|
1149
1271
|
mirror: true,
|
|
1150
1272
|
displayMirror: false,
|
|
1273
|
+
compileMirror: true,
|
|
1151
1274
|
Label: "\u222F",
|
|
1152
1275
|
title: "\u062A\u0643\u0627\u0645\u0644 \u0633\u0637\u062D\u064A \u0645\u063A\u0644\u0642",
|
|
1153
1276
|
svg_path: null
|
|
@@ -1158,6 +1281,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
|
|
|
1158
1281
|
Tex: "\\oiiint",
|
|
1159
1282
|
mirror: true,
|
|
1160
1283
|
displayMirror: false,
|
|
1284
|
+
compileMirror: true,
|
|
1161
1285
|
Label: "\u2230",
|
|
1162
1286
|
title: "\u062A\u0643\u0627\u0645\u0644 \u062D\u062C\u0645\u064A \u0645\u063A\u0644\u0642",
|
|
1163
1287
|
svg_path: null
|
|
@@ -1167,8 +1291,9 @@ function shouldMirrorOperatorDisplay(command) {
|
|
|
1167
1291
|
return command?.displayMirror ?? command?.mirror ?? false;
|
|
1168
1292
|
}
|
|
1169
1293
|
var MIRRORED_OPERATOR_TEX = Object.values(ATOMIC_OPERATOR_COMMANDS).filter((command) => command.mirror).map((command) => command.Tex).sort((a, b) => b.length - a.length);
|
|
1170
|
-
|
|
1171
|
-
|
|
1294
|
+
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);
|
|
1295
|
+
function matchingMirroredOperatorFrom(tex, index, operatorTexList) {
|
|
1296
|
+
for (const operatorTex of operatorTexList) {
|
|
1172
1297
|
if (!tex.startsWith(operatorTex, index)) {
|
|
1173
1298
|
continue;
|
|
1174
1299
|
}
|
|
@@ -1199,19 +1324,26 @@ function findMatchingBrace(tex, openIndex) {
|
|
|
1199
1324
|
}
|
|
1200
1325
|
return -1;
|
|
1201
1326
|
}
|
|
1202
|
-
function mirrorBuTeXOperatorsInTex(tex) {
|
|
1327
|
+
function mirrorBuTeXOperatorsInTex(tex, options = {}) {
|
|
1328
|
+
const mirroredOperatorTex = options.target === "compile" ? COMPILE_MIRRORED_OPERATOR_TEX : MIRRORED_OPERATOR_TEX;
|
|
1203
1329
|
let result = "";
|
|
1204
1330
|
let index = 0;
|
|
1205
1331
|
while (index < tex.length) {
|
|
1206
1332
|
if (tex.startsWith("\\butexmirror{", index)) {
|
|
1207
1333
|
const end = findMatchingBrace(tex, index + "\\butexmirror".length);
|
|
1208
1334
|
if (end !== -1) {
|
|
1209
|
-
|
|
1335
|
+
const bodyStart = index + "\\butexmirror{".length;
|
|
1336
|
+
const body = tex.slice(bodyStart, end);
|
|
1337
|
+
if (options.target === "compile" && MIRRORED_OPERATOR_TEX.includes(body) && !mirroredOperatorTex.includes(body)) {
|
|
1338
|
+
result += body;
|
|
1339
|
+
} else {
|
|
1340
|
+
result += tex.slice(index, end + 1);
|
|
1341
|
+
}
|
|
1210
1342
|
index = end + 1;
|
|
1211
1343
|
continue;
|
|
1212
1344
|
}
|
|
1213
1345
|
}
|
|
1214
|
-
const operatorTex =
|
|
1346
|
+
const operatorTex = matchingMirroredOperatorFrom(tex, index, mirroredOperatorTex);
|
|
1215
1347
|
if (operatorTex) {
|
|
1216
1348
|
result += `\\butexmirror{${operatorTex}}`;
|
|
1217
1349
|
index += operatorTex.length;
|
|
@@ -6884,6 +7016,11 @@ var WIDGET_CHROME_CSS = `
|
|
|
6884
7016
|
font-family: ${BUTEX_DIWANI_OUTLINE_FONT_STACK};
|
|
6885
7017
|
}
|
|
6886
7018
|
|
|
7019
|
+
.butex-widget .font-mode-btn--maghribi,
|
|
7020
|
+
.butex-widget .character-font-option--maghribi {
|
|
7021
|
+
font-family: ${BUTEX_MAGHRIBI_FONT_STACK};
|
|
7022
|
+
}
|
|
7023
|
+
|
|
6887
7024
|
.butex-widget .character-font-options {
|
|
6888
7025
|
position: absolute;
|
|
6889
7026
|
z-index: 10;
|
|
@@ -7418,6 +7555,36 @@ var WIDGET_CHROME_CSS = `
|
|
|
7418
7555
|
background: var(--butex-dev-inset-bg);
|
|
7419
7556
|
color: var(--butex-dev-inset-fg);
|
|
7420
7557
|
}
|
|
7558
|
+
|
|
7559
|
+
.butex-widget .debug-json-import {
|
|
7560
|
+
display: grid;
|
|
7561
|
+
gap: 8px;
|
|
7562
|
+
margin-bottom: 10px;
|
|
7563
|
+
}
|
|
7564
|
+
|
|
7565
|
+
.butex-widget .debug-json-import textarea {
|
|
7566
|
+
min-height: 150px;
|
|
7567
|
+
resize: vertical;
|
|
7568
|
+
border: 1px solid var(--butex-dev-inset-border);
|
|
7569
|
+
border-radius: 8px;
|
|
7570
|
+
padding: 8px 10px;
|
|
7571
|
+
direction: ltr;
|
|
7572
|
+
text-align: left;
|
|
7573
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
7574
|
+
font-size: 11px;
|
|
7575
|
+
background: var(--butex-dev-inset-bg);
|
|
7576
|
+
color: var(--butex-dev-inset-fg);
|
|
7577
|
+
}
|
|
7578
|
+
|
|
7579
|
+
.butex-widget .debug-json-error {
|
|
7580
|
+
margin: 0;
|
|
7581
|
+
border: 1px solid rgba(220, 38, 38, 0.45);
|
|
7582
|
+
background: rgba(254, 226, 226, 0.9);
|
|
7583
|
+
color: #991b1b;
|
|
7584
|
+
border-radius: 8px;
|
|
7585
|
+
padding: 8px 10px;
|
|
7586
|
+
white-space: pre-wrap;
|
|
7587
|
+
}
|
|
7421
7588
|
`.trim();
|
|
7422
7589
|
var CHROME_STYLE_ID = "butex-widget-chrome-css";
|
|
7423
7590
|
function injectWidgetChromeCss(doc) {
|
|
@@ -7436,6 +7603,1026 @@ function uiLocaleDirection(locale) {
|
|
|
7436
7603
|
return locale === "ar" ? "rtl" : "ltr";
|
|
7437
7604
|
}
|
|
7438
7605
|
|
|
7606
|
+
// src/ast/commands/index.ts
|
|
7607
|
+
function renderCommandCore(context) {
|
|
7608
|
+
const optional = context.optionalArgs.map((arg) => `[${context.renderChain(arg)}]`).join("");
|
|
7609
|
+
const mandatory = context.mandatoryArgs.map((arg) => `{${context.renderChain(arg)}}`).join("");
|
|
7610
|
+
return context.name + optional + mandatory;
|
|
7611
|
+
}
|
|
7612
|
+
|
|
7613
|
+
// src/ast/arabic_ast.ts
|
|
7614
|
+
var State = class {
|
|
7615
|
+
// Empty for now, like the Python State placeholder used by BaseNode.
|
|
7616
|
+
};
|
|
7617
|
+
var BaseAstNode = class {
|
|
7618
|
+
state;
|
|
7619
|
+
superscript;
|
|
7620
|
+
subscript;
|
|
7621
|
+
nodeType;
|
|
7622
|
+
constructor(state = null) {
|
|
7623
|
+
if (state === null) {
|
|
7624
|
+
state = new State();
|
|
7625
|
+
}
|
|
7626
|
+
this.state = state;
|
|
7627
|
+
this.superscript = null;
|
|
7628
|
+
this.subscript = null;
|
|
7629
|
+
this.nodeType = this.constructor.name;
|
|
7630
|
+
}
|
|
7631
|
+
latex() {
|
|
7632
|
+
throw new Error("NotImplementedError");
|
|
7633
|
+
}
|
|
7634
|
+
arabicLatex() {
|
|
7635
|
+
throw new Error("NotImplementedError");
|
|
7636
|
+
}
|
|
7637
|
+
toArabicLatex() {
|
|
7638
|
+
return this.arabicLatex();
|
|
7639
|
+
}
|
|
7640
|
+
/** Latin-style scripts: `^{...}` and `_{...}` for english_json rendering. */
|
|
7641
|
+
latexScripts() {
|
|
7642
|
+
let s = "";
|
|
7643
|
+
if (this.superscript !== null) {
|
|
7644
|
+
s += "^{" + this.superscript.latex() + "}";
|
|
7645
|
+
}
|
|
7646
|
+
if (this.subscript !== null) {
|
|
7647
|
+
s += "_{" + this.subscript.latex() + "}";
|
|
7648
|
+
}
|
|
7649
|
+
return s;
|
|
7650
|
+
}
|
|
7651
|
+
/**
|
|
7652
|
+
* Arabic scripts use \\prescript{sup}{sub}{content} (matches reference Python output).
|
|
7653
|
+
* Call with rendered strings for sup/sub chains (may be empty strings).
|
|
7654
|
+
*/
|
|
7655
|
+
arabicLatexScripts(sup, sub, content) {
|
|
7656
|
+
if (sup !== "" || sub !== "") {
|
|
7657
|
+
return "\\prescript{" + sup + "}{" + sub + "}{" + content + "}";
|
|
7658
|
+
}
|
|
7659
|
+
return content;
|
|
7660
|
+
}
|
|
7661
|
+
};
|
|
7662
|
+
var ChainNode = class {
|
|
7663
|
+
chain;
|
|
7664
|
+
constructor(chain = []) {
|
|
7665
|
+
this.chain = chain;
|
|
7666
|
+
}
|
|
7667
|
+
latex() {
|
|
7668
|
+
return this.chain.map((node) => node.latex()).join(" ");
|
|
7669
|
+
}
|
|
7670
|
+
toEnglishLatex() {
|
|
7671
|
+
return this.chain.map((node) => node.latex()).join(" ");
|
|
7672
|
+
}
|
|
7673
|
+
/** RTL: reverse order relative to Latin chain (see test/ref_tests.txt). */
|
|
7674
|
+
arabicLatex() {
|
|
7675
|
+
const reversed = this.chain.slice().reverse();
|
|
7676
|
+
return reversed.map((node) => node.arabicLatex()).join(" ");
|
|
7677
|
+
}
|
|
7678
|
+
toArabicLatex() {
|
|
7679
|
+
return this.arabicLatex();
|
|
7680
|
+
}
|
|
7681
|
+
};
|
|
7682
|
+
var NumberNode = class extends BaseAstNode {
|
|
7683
|
+
expr;
|
|
7684
|
+
constructor(expr, state = null) {
|
|
7685
|
+
super(state);
|
|
7686
|
+
this.nodeType = "NumberObject";
|
|
7687
|
+
this.expr = expr;
|
|
7688
|
+
}
|
|
7689
|
+
latex() {
|
|
7690
|
+
return this.expr + this.latexScripts();
|
|
7691
|
+
}
|
|
7692
|
+
arabicLatex() {
|
|
7693
|
+
const sup = this.superscript !== null ? this.superscript.arabicLatex() : "";
|
|
7694
|
+
const sub = this.subscript !== null ? this.subscript.arabicLatex() : "";
|
|
7695
|
+
return this.arabicLatexScripts(sup, sub, this.expr);
|
|
7696
|
+
}
|
|
7697
|
+
};
|
|
7698
|
+
var CharNode = class extends BaseAstNode {
|
|
7699
|
+
expr;
|
|
7700
|
+
constructor(expr, state = null) {
|
|
7701
|
+
super(state);
|
|
7702
|
+
this.nodeType = "CharObject";
|
|
7703
|
+
this.expr = expr;
|
|
7704
|
+
}
|
|
7705
|
+
latex() {
|
|
7706
|
+
return this.expr + this.latexScripts();
|
|
7707
|
+
}
|
|
7708
|
+
arabicLatex() {
|
|
7709
|
+
const sup = this.superscript !== null ? this.superscript.arabicLatex() : "";
|
|
7710
|
+
const sub = this.subscript !== null ? this.subscript.arabicLatex() : "";
|
|
7711
|
+
return this.arabicLatexScripts(sup, sub, this.expr);
|
|
7712
|
+
}
|
|
7713
|
+
};
|
|
7714
|
+
var OperatorNode = class extends BaseAstNode {
|
|
7715
|
+
expr;
|
|
7716
|
+
constructor(expr, state = null) {
|
|
7717
|
+
super(state);
|
|
7718
|
+
this.nodeType = "OperatorObject";
|
|
7719
|
+
this.expr = expr;
|
|
7720
|
+
}
|
|
7721
|
+
latex() {
|
|
7722
|
+
return this.expr;
|
|
7723
|
+
}
|
|
7724
|
+
arabicLatex() {
|
|
7725
|
+
return this.expr;
|
|
7726
|
+
}
|
|
7727
|
+
};
|
|
7728
|
+
var DelimiterNode = class extends BaseAstNode {
|
|
7729
|
+
leftDelimExpr;
|
|
7730
|
+
innerExpr;
|
|
7731
|
+
rightDelimExpr;
|
|
7732
|
+
constructor(leftDelimExpr, innerExpr, rightDelimExpr, state = null) {
|
|
7733
|
+
super(state);
|
|
7734
|
+
this.nodeType = "DelimiterObject";
|
|
7735
|
+
this.leftDelimExpr = leftDelimExpr;
|
|
7736
|
+
this.innerExpr = innerExpr;
|
|
7737
|
+
this.rightDelimExpr = rightDelimExpr;
|
|
7738
|
+
}
|
|
7739
|
+
latex() {
|
|
7740
|
+
return this.leftDelimExpr + this.innerExpr.latex() + this.rightDelimExpr + this.latexScripts();
|
|
7741
|
+
}
|
|
7742
|
+
arabicLatex() {
|
|
7743
|
+
const sup = this.superscript !== null ? this.superscript.arabicLatex() : "";
|
|
7744
|
+
const sub = this.subscript !== null ? this.subscript.arabicLatex() : "";
|
|
7745
|
+
const content = this.leftDelimExpr + this.innerExpr.arabicLatex() + this.rightDelimExpr;
|
|
7746
|
+
return this.arabicLatexScripts(sup, sub, content);
|
|
7747
|
+
}
|
|
7748
|
+
};
|
|
7749
|
+
var CommandNode = class extends BaseAstNode {
|
|
7750
|
+
name;
|
|
7751
|
+
optionalArgs;
|
|
7752
|
+
mandatoryArgs;
|
|
7753
|
+
constructor(name, optionalArgs = [], mandatoryArgs = [], state = null) {
|
|
7754
|
+
super(state);
|
|
7755
|
+
this.nodeType = "CommandObject";
|
|
7756
|
+
this.name = name;
|
|
7757
|
+
this.optionalArgs = optionalArgs;
|
|
7758
|
+
this.mandatoryArgs = mandatoryArgs;
|
|
7759
|
+
}
|
|
7760
|
+
latex() {
|
|
7761
|
+
const content = renderCommandCore({
|
|
7762
|
+
name: this.name,
|
|
7763
|
+
optionalArgs: this.optionalArgs,
|
|
7764
|
+
mandatoryArgs: this.mandatoryArgs,
|
|
7765
|
+
renderChain: (chain) => chain.latex()
|
|
7766
|
+
});
|
|
7767
|
+
return content + this.latexScripts();
|
|
7768
|
+
}
|
|
7769
|
+
arabicLatex() {
|
|
7770
|
+
const sup = this.superscript !== null ? this.superscript.arabicLatex() : "";
|
|
7771
|
+
const sub = this.subscript !== null ? this.subscript.arabicLatex() : "";
|
|
7772
|
+
const arabicName = this.name === "\\sqrt" || this.name === "\\arabsqrt" ? "\\arsqrt" : this.name;
|
|
7773
|
+
const content = renderCommandCore({
|
|
7774
|
+
name: arabicName,
|
|
7775
|
+
optionalArgs: this.optionalArgs,
|
|
7776
|
+
mandatoryArgs: this.mandatoryArgs,
|
|
7777
|
+
renderChain: (chain) => chain.arabicLatex()
|
|
7778
|
+
});
|
|
7779
|
+
return this.arabicLatexScripts(sup, sub, content);
|
|
7780
|
+
}
|
|
7781
|
+
};
|
|
7782
|
+
var EnvNode = class extends BaseAstNode {
|
|
7783
|
+
opening;
|
|
7784
|
+
lines;
|
|
7785
|
+
closing;
|
|
7786
|
+
constructor(opening, lines = [], closing, state = null) {
|
|
7787
|
+
super(state);
|
|
7788
|
+
this.nodeType = "EnvObject";
|
|
7789
|
+
this.opening = opening;
|
|
7790
|
+
this.lines = lines;
|
|
7791
|
+
this.closing = closing;
|
|
7792
|
+
}
|
|
7793
|
+
latex() {
|
|
7794
|
+
if (this.lines.length === 0) {
|
|
7795
|
+
return this.opening + this.closing + this.latexScripts();
|
|
7796
|
+
}
|
|
7797
|
+
const formattedLines = this.lines.map((line) => ` ${line.latex()}`);
|
|
7798
|
+
const content = formattedLines.join(" \\\\\n");
|
|
7799
|
+
return `${this.opening}
|
|
7800
|
+
${content}
|
|
7801
|
+
${this.closing}` + this.latexScripts();
|
|
7802
|
+
}
|
|
7803
|
+
arabicLatex() {
|
|
7804
|
+
const sup = this.superscript !== null ? this.superscript.arabicLatex() : "";
|
|
7805
|
+
const sub = this.subscript !== null ? this.subscript.arabicLatex() : "";
|
|
7806
|
+
if (this.lines.length === 0) {
|
|
7807
|
+
return this.arabicLatexScripts(sup, sub, this.opening + this.closing);
|
|
7808
|
+
}
|
|
7809
|
+
const formattedLines = this.lines.map((line) => ` ${line.arabicLatex()}`);
|
|
7810
|
+
const content = formattedLines.join(" \\\\\n");
|
|
7811
|
+
const fullContent = `${this.opening}
|
|
7812
|
+
${content}
|
|
7813
|
+
${this.closing}`;
|
|
7814
|
+
return this.arabicLatexScripts(sup, sub, fullContent);
|
|
7815
|
+
}
|
|
7816
|
+
};
|
|
7817
|
+
function parseScripts(node, json, mode) {
|
|
7818
|
+
if (json.superscript) {
|
|
7819
|
+
node.superscript = parseChain(json.superscript, mode);
|
|
7820
|
+
}
|
|
7821
|
+
if (json.subscript) {
|
|
7822
|
+
node.subscript = parseChain(json.subscript, mode);
|
|
7823
|
+
}
|
|
7824
|
+
}
|
|
7825
|
+
function parseNode(json, mode) {
|
|
7826
|
+
if (json.node_type === "DelimiterObject") {
|
|
7827
|
+
const node2 = parseDelimiter(json, mode);
|
|
7828
|
+
parseScripts(node2, json, mode);
|
|
7829
|
+
return node2;
|
|
7830
|
+
}
|
|
7831
|
+
if (json.node_type === "OperatorObject") {
|
|
7832
|
+
if (typeof json.expr !== "string") {
|
|
7833
|
+
throw new Error("OperatorObject requires string expr");
|
|
7834
|
+
}
|
|
7835
|
+
const node2 = new OperatorNode(json.expr);
|
|
7836
|
+
parseScripts(node2, json, mode);
|
|
7837
|
+
return node2;
|
|
7838
|
+
}
|
|
7839
|
+
if (json.node_type === "CommandObject") {
|
|
7840
|
+
const node2 = parseCommand(json, mode);
|
|
7841
|
+
parseScripts(node2, json, mode);
|
|
7842
|
+
return node2;
|
|
7843
|
+
}
|
|
7844
|
+
if (json.node_type === "EnvObject") {
|
|
7845
|
+
const node2 = parseEnv(json, mode);
|
|
7846
|
+
parseScripts(node2, json, mode);
|
|
7847
|
+
return node2;
|
|
7848
|
+
}
|
|
7849
|
+
if (typeof json.expr !== "string") {
|
|
7850
|
+
throw new Error(`${json.node_type} requires string expr`);
|
|
7851
|
+
}
|
|
7852
|
+
let node;
|
|
7853
|
+
if (json.node_type === "NumberObject") {
|
|
7854
|
+
node = new NumberNode(json.expr);
|
|
7855
|
+
} else if (json.node_type === "CharObject") {
|
|
7856
|
+
node = new CharNode(json.expr);
|
|
7857
|
+
} else {
|
|
7858
|
+
throw new Error(`Unsupported node_type: ${json.node_type}`);
|
|
7859
|
+
}
|
|
7860
|
+
parseScripts(node, json, mode);
|
|
7861
|
+
return node;
|
|
7862
|
+
}
|
|
7863
|
+
function parseDelimiter(json, mode) {
|
|
7864
|
+
if (typeof json.left_delim_expr !== "string") {
|
|
7865
|
+
throw new Error("DelimiterObject requires string left_delim_expr");
|
|
7866
|
+
}
|
|
7867
|
+
if (!json.inner_expr || json.inner_expr.node_type !== "ChainClass") {
|
|
7868
|
+
throw new Error("DelimiterObject requires ChainClass inner_expr");
|
|
7869
|
+
}
|
|
7870
|
+
if (typeof json.right_delim_expr !== "string") {
|
|
7871
|
+
throw new Error("DelimiterObject requires string right_delim_expr");
|
|
7872
|
+
}
|
|
7873
|
+
const innerExpr = parseChain(json.inner_expr, mode);
|
|
7874
|
+
return new DelimiterNode(json.left_delim_expr, innerExpr, json.right_delim_expr);
|
|
7875
|
+
}
|
|
7876
|
+
function parseCommand(json, mode) {
|
|
7877
|
+
if (typeof json.name !== "string") {
|
|
7878
|
+
throw new Error("CommandObject requires string name");
|
|
7879
|
+
}
|
|
7880
|
+
const optionalJson = Array.isArray(json.optional_args) ? json.optional_args : [];
|
|
7881
|
+
const mandatoryJson = Array.isArray(json.mandatory_args) ? json.mandatory_args : [];
|
|
7882
|
+
const optionalArgs = optionalJson.map((arg) => parseChain(arg, mode));
|
|
7883
|
+
const mandatoryArgs = mandatoryJson.map((arg) => parseChain(arg, mode));
|
|
7884
|
+
return new CommandNode(json.name, optionalArgs, mandatoryArgs);
|
|
7885
|
+
}
|
|
7886
|
+
function parseEnv(json, mode) {
|
|
7887
|
+
if (typeof json.opening !== "string") {
|
|
7888
|
+
throw new Error("EnvObject requires string opening");
|
|
7889
|
+
}
|
|
7890
|
+
if (typeof json.closing !== "string") {
|
|
7891
|
+
throw new Error("EnvObject requires string closing");
|
|
7892
|
+
}
|
|
7893
|
+
if (!Array.isArray(json.lines)) {
|
|
7894
|
+
throw new Error("EnvObject requires lines array");
|
|
7895
|
+
}
|
|
7896
|
+
const lines = json.lines.map((line) => parseChain(line, mode));
|
|
7897
|
+
return new EnvNode(json.opening, lines, json.closing);
|
|
7898
|
+
}
|
|
7899
|
+
function parseChain(json, mode) {
|
|
7900
|
+
if (json.node_type !== "ChainClass") {
|
|
7901
|
+
throw new Error(`Expected ChainClass, got: ${json.node_type}`);
|
|
7902
|
+
}
|
|
7903
|
+
const nodes = json.chain.map((childJson) => parseNode(childJson, mode));
|
|
7904
|
+
return new ChainNode(nodes);
|
|
7905
|
+
}
|
|
7906
|
+
function fromEnglishJson(json) {
|
|
7907
|
+
if (json.node_type === "ChainClass") {
|
|
7908
|
+
return parseChain(json, "english");
|
|
7909
|
+
}
|
|
7910
|
+
return parseNode(json, "english");
|
|
7911
|
+
}
|
|
7912
|
+
function fromArabicJson(json) {
|
|
7913
|
+
if (json.node_type === "ChainClass") {
|
|
7914
|
+
return parseChain(json, "arabic");
|
|
7915
|
+
}
|
|
7916
|
+
return parseNode(json, "arabic");
|
|
7917
|
+
}
|
|
7918
|
+
|
|
7919
|
+
// src/document/mathObject.ts
|
|
7920
|
+
function isObject(value) {
|
|
7921
|
+
return typeof value === "object" && value !== null;
|
|
7922
|
+
}
|
|
7923
|
+
function isMathObjectJson(value) {
|
|
7924
|
+
return isObject(value) && value.node_type === "MathObject";
|
|
7925
|
+
}
|
|
7926
|
+
function assertChainNode(value) {
|
|
7927
|
+
if (!(value instanceof ChainNode)) {
|
|
7928
|
+
throw new Error("MathObject lines must parse to ChainNode");
|
|
7929
|
+
}
|
|
7930
|
+
return value;
|
|
7931
|
+
}
|
|
7932
|
+
function fromMathObjectJson(json, mode = "english") {
|
|
7933
|
+
if (!isMathObjectJson(json)) {
|
|
7934
|
+
throw new Error('MathObject requires node_type "MathObject"');
|
|
7935
|
+
}
|
|
7936
|
+
if (typeof json.math_mode !== "string") {
|
|
7937
|
+
throw new Error("MathObject requires string math_mode");
|
|
7938
|
+
}
|
|
7939
|
+
if (typeof json.closing !== "string") {
|
|
7940
|
+
throw new Error("MathObject requires string closing");
|
|
7941
|
+
}
|
|
7942
|
+
if (!Array.isArray(json.lines) || json.lines.length === 0) {
|
|
7943
|
+
throw new Error("MathObject requires non-empty lines array");
|
|
7944
|
+
}
|
|
7945
|
+
const parseChain2 = mode === "arabic" ? fromArabicJson : fromEnglishJson;
|
|
7946
|
+
const lines = json.lines.map((line) => assertChainNode(parseChain2(line)));
|
|
7947
|
+
return {
|
|
7948
|
+
nodeType: "MathObject",
|
|
7949
|
+
mathMode: json.math_mode,
|
|
7950
|
+
lines,
|
|
7951
|
+
closing: json.closing
|
|
7952
|
+
};
|
|
7953
|
+
}
|
|
7954
|
+
function scriptsToJson(node, path) {
|
|
7955
|
+
return {
|
|
7956
|
+
...node.superscript ? { superscript: chainToJson(node.superscript, `${path}.superscript`) } : {},
|
|
7957
|
+
...node.subscript ? { subscript: chainToJson(node.subscript, `${path}.subscript`) } : {}
|
|
7958
|
+
};
|
|
7959
|
+
}
|
|
7960
|
+
function nodeToJson(node, path) {
|
|
7961
|
+
const scripts = scriptsToJson(node, path);
|
|
7962
|
+
if (node instanceof CharNode || node instanceof NumberNode || node instanceof OperatorNode) {
|
|
7963
|
+
return { node_type: node.nodeType, expr: node.expr, ...scripts };
|
|
7964
|
+
}
|
|
7965
|
+
if (node instanceof DelimiterNode) {
|
|
7966
|
+
return {
|
|
7967
|
+
node_type: "DelimiterObject",
|
|
7968
|
+
left_delim_expr: node.leftDelimExpr,
|
|
7969
|
+
inner_expr: chainToJson(node.innerExpr, `${path}.inner_expr`),
|
|
7970
|
+
right_delim_expr: node.rightDelimExpr,
|
|
7971
|
+
...scripts
|
|
7972
|
+
};
|
|
7973
|
+
}
|
|
7974
|
+
if (node instanceof CommandNode) {
|
|
7975
|
+
return {
|
|
7976
|
+
node_type: "CommandObject",
|
|
7977
|
+
name: node.name,
|
|
7978
|
+
optional_args: node.optionalArgs.map((arg, index) => chainToJson(arg, `${path}.optional_args[${String(index)}]`)),
|
|
7979
|
+
mandatory_args: node.mandatoryArgs.map((arg, index) => chainToJson(arg, `${path}.mandatory_args[${String(index)}]`)),
|
|
7980
|
+
...scripts
|
|
7981
|
+
};
|
|
7982
|
+
}
|
|
7983
|
+
if (node instanceof EnvNode) {
|
|
7984
|
+
return {
|
|
7985
|
+
node_type: "EnvObject",
|
|
7986
|
+
opening: node.opening,
|
|
7987
|
+
lines: node.lines.map((line, index) => chainToJson(line, `${path}.lines[${String(index)}]`)),
|
|
7988
|
+
closing: node.closing,
|
|
7989
|
+
...scripts
|
|
7990
|
+
};
|
|
7991
|
+
}
|
|
7992
|
+
throw new Error(`Unsupported runtime math node at ${path}: ${node.nodeType}`);
|
|
7993
|
+
}
|
|
7994
|
+
function chainToJson(chain, path) {
|
|
7995
|
+
if (!(chain instanceof ChainNode)) {
|
|
7996
|
+
throw new Error(`Expected live ChainNode at ${path}`);
|
|
7997
|
+
}
|
|
7998
|
+
return {
|
|
7999
|
+
node_type: "ChainClass",
|
|
8000
|
+
chain: chain.chain.map((node, index) => nodeToJson(node, `${path}.chain[${String(index)}]`))
|
|
8001
|
+
};
|
|
8002
|
+
}
|
|
8003
|
+
function toMathObjectJson(math) {
|
|
8004
|
+
if (math.nodeType !== "MathObject" || !Array.isArray(math.lines) || math.lines.length === 0) {
|
|
8005
|
+
throw new Error("Cannot serialize invalid runtime MathObject");
|
|
8006
|
+
}
|
|
8007
|
+
return {
|
|
8008
|
+
node_type: "MathObject",
|
|
8009
|
+
math_mode: math.mathMode,
|
|
8010
|
+
lines: math.lines.map((line, index) => chainToJson(line, `$.lines[${String(index)}]`)),
|
|
8011
|
+
closing: math.closing
|
|
8012
|
+
};
|
|
8013
|
+
}
|
|
8014
|
+
|
|
8015
|
+
// src/document/normalizeCharImport.ts
|
|
8016
|
+
var WRAPPER_SPECS = [
|
|
8017
|
+
...NON_DEFAULT_CHARACTER_FONT_SPECS.flatMap((font) => [
|
|
8018
|
+
{ prefix: font.macro, font: font.id },
|
|
8019
|
+
...(font.importAliases ?? []).map((alias) => ({ prefix: alias, font: font.id }))
|
|
8020
|
+
]),
|
|
8021
|
+
{ prefix: "\\text" }
|
|
8022
|
+
];
|
|
8023
|
+
function readBracedArg(source, openBraceIndex) {
|
|
8024
|
+
if (source[openBraceIndex] !== "{") {
|
|
8025
|
+
return null;
|
|
8026
|
+
}
|
|
8027
|
+
let depth = 0;
|
|
8028
|
+
for (let index = openBraceIndex; index < source.length; index += 1) {
|
|
8029
|
+
const char = source[index];
|
|
8030
|
+
if (char === "{") {
|
|
8031
|
+
depth += 1;
|
|
8032
|
+
} else if (char === "}") {
|
|
8033
|
+
depth -= 1;
|
|
8034
|
+
if (depth === 0) {
|
|
8035
|
+
return { inner: source.slice(openBraceIndex + 1, index), end: index + 1 };
|
|
8036
|
+
}
|
|
8037
|
+
}
|
|
8038
|
+
}
|
|
8039
|
+
return null;
|
|
8040
|
+
}
|
|
8041
|
+
function peelWrapper(source) {
|
|
8042
|
+
for (const wrapper of WRAPPER_SPECS) {
|
|
8043
|
+
if (!source.startsWith(wrapper.prefix)) {
|
|
8044
|
+
continue;
|
|
8045
|
+
}
|
|
8046
|
+
const braced = readBracedArg(source, wrapper.prefix.length);
|
|
8047
|
+
if (!braced || braced.end !== source.length) {
|
|
8048
|
+
continue;
|
|
8049
|
+
}
|
|
8050
|
+
return { inner: braced.inner, font: wrapper.font };
|
|
8051
|
+
}
|
|
8052
|
+
return null;
|
|
8053
|
+
}
|
|
8054
|
+
function normalizeCharImportExpr(expr) {
|
|
8055
|
+
const original = expr;
|
|
8056
|
+
let current = expr;
|
|
8057
|
+
let characterFont = "default";
|
|
8058
|
+
let changed = false;
|
|
8059
|
+
while (true) {
|
|
8060
|
+
const peeled = peelWrapper(current);
|
|
8061
|
+
if (!peeled) {
|
|
8062
|
+
break;
|
|
8063
|
+
}
|
|
8064
|
+
current = peeled.inner;
|
|
8065
|
+
if (peeled.font) {
|
|
8066
|
+
characterFont = peeled.font;
|
|
8067
|
+
}
|
|
8068
|
+
changed = true;
|
|
8069
|
+
}
|
|
8070
|
+
if (!changed) {
|
|
8071
|
+
return { expr: original, characterFont: "default" };
|
|
8072
|
+
}
|
|
8073
|
+
if (current.includes("\\")) {
|
|
8074
|
+
return { expr: original, characterFont: "default" };
|
|
8075
|
+
}
|
|
8076
|
+
return { expr: current, characterFont };
|
|
8077
|
+
}
|
|
8078
|
+
|
|
8079
|
+
// src/document/mathEditorAdapter.ts
|
|
8080
|
+
var COMMAND_FONT_MAP = Object.fromEntries([
|
|
8081
|
+
["\\text", "infer"],
|
|
8082
|
+
...NON_DEFAULT_CHARACTER_FONT_SPECS.flatMap((font) => [
|
|
8083
|
+
[font.macro, font.id],
|
|
8084
|
+
...(font.importAliases ?? []).map((alias) => [alias, font.id])
|
|
8085
|
+
])
|
|
8086
|
+
]);
|
|
8087
|
+
var CHAR_FONT_EXPORT_TEX = Object.fromEntries(
|
|
8088
|
+
NON_DEFAULT_CHARACTER_FONT_SPECS.map((font) => [font.id, font.macro])
|
|
8089
|
+
);
|
|
8090
|
+
function charEditorNodeToAstNode(node) {
|
|
8091
|
+
const font = node.characterFont ?? "default";
|
|
8092
|
+
const charNode = new CharNode(node.expr);
|
|
8093
|
+
if (font === "default") {
|
|
8094
|
+
return charNode;
|
|
8095
|
+
}
|
|
8096
|
+
return new CommandNode(CHAR_FONT_EXPORT_TEX[font], [], [new ChainNode([charNode])]);
|
|
8097
|
+
}
|
|
8098
|
+
function commandIdForTex(tex) {
|
|
8099
|
+
for (const spec of Object.values(ATOMIC_COMMANDS)) {
|
|
8100
|
+
const renderTex = spec.arabicRenderTex;
|
|
8101
|
+
if (spec.englishTex === tex || spec.arabicTex === tex || renderTex === tex) {
|
|
8102
|
+
return spec.id;
|
|
8103
|
+
}
|
|
8104
|
+
}
|
|
8105
|
+
return null;
|
|
8106
|
+
}
|
|
8107
|
+
function operatorCommandIdForTex(tex) {
|
|
8108
|
+
for (const spec of Object.values(ATOMIC_OPERATOR_COMMANDS)) {
|
|
8109
|
+
if (spec.Tex === tex) {
|
|
8110
|
+
return spec.id;
|
|
8111
|
+
}
|
|
8112
|
+
}
|
|
8113
|
+
return null;
|
|
8114
|
+
}
|
|
8115
|
+
function cloneChainWithFreshIds(chain) {
|
|
8116
|
+
return structuredClone(chain);
|
|
8117
|
+
}
|
|
8118
|
+
function attachScripts(astNode, editorNode) {
|
|
8119
|
+
if (astNode.superscript) {
|
|
8120
|
+
const sup = chainToEditorChain(astNode.superscript);
|
|
8121
|
+
if (!sup.editable) {
|
|
8122
|
+
return sup;
|
|
8123
|
+
}
|
|
8124
|
+
editorNode.superscript = sup.chain;
|
|
8125
|
+
}
|
|
8126
|
+
if (astNode.subscript) {
|
|
8127
|
+
const sub = chainToEditorChain(astNode.subscript);
|
|
8128
|
+
if (!sub.editable) {
|
|
8129
|
+
return sub;
|
|
8130
|
+
}
|
|
8131
|
+
editorNode.subscript = sub.chain;
|
|
8132
|
+
}
|
|
8133
|
+
return null;
|
|
8134
|
+
}
|
|
8135
|
+
var MATRIX_ENV_NAMES = /* @__PURE__ */ new Set(["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix"]);
|
|
8136
|
+
function isGridEnvName(value) {
|
|
8137
|
+
return MATRIX_ENV_NAMES.has(value) || value === "array" || value === "aligned";
|
|
8138
|
+
}
|
|
8139
|
+
function isMatrixEnvName(value) {
|
|
8140
|
+
return MATRIX_ENV_NAMES.has(value);
|
|
8141
|
+
}
|
|
8142
|
+
function parseEnvOpening(opening) {
|
|
8143
|
+
const match = /^\\begin\{([^}]+)\}(?:\{([lcr]+)\})?$/.exec(opening);
|
|
8144
|
+
if (!match) {
|
|
8145
|
+
return null;
|
|
8146
|
+
}
|
|
8147
|
+
const envName = match[1] ?? "";
|
|
8148
|
+
if (!isGridEnvName(envName)) {
|
|
8149
|
+
return null;
|
|
8150
|
+
}
|
|
8151
|
+
if (envName === "array") {
|
|
8152
|
+
const spec = match[2] ?? "c";
|
|
8153
|
+
return {
|
|
8154
|
+
envName,
|
|
8155
|
+
alignments: spec.split("").map((alignment) => alignment)
|
|
8156
|
+
};
|
|
8157
|
+
}
|
|
8158
|
+
return { envName };
|
|
8159
|
+
}
|
|
8160
|
+
function splitEnvLine(line) {
|
|
8161
|
+
const cells = [];
|
|
8162
|
+
let current = [];
|
|
8163
|
+
for (const node of line.chain) {
|
|
8164
|
+
if (node instanceof OperatorNode && node.expr === "&") {
|
|
8165
|
+
cells.push(new ChainNode(current));
|
|
8166
|
+
current = [];
|
|
8167
|
+
} else {
|
|
8168
|
+
current.push(node);
|
|
8169
|
+
}
|
|
8170
|
+
}
|
|
8171
|
+
cells.push(new ChainNode(current));
|
|
8172
|
+
return cells;
|
|
8173
|
+
}
|
|
8174
|
+
function envToEditorNode(node) {
|
|
8175
|
+
const parsed = parseEnvOpening(node.opening);
|
|
8176
|
+
if (!parsed) {
|
|
8177
|
+
return { editable: false, reason: `\u0628\u064A\u0626\u0629 \u0631\u064A\u0627\u0636\u064A\u0629 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645\u0629 \u062D\u0627\u0644\u064A\u0627: ${node.opening}` };
|
|
8178
|
+
}
|
|
8179
|
+
const expectedClosing = `\\end{${parsed.envName}}`;
|
|
8180
|
+
if (node.closing !== expectedClosing) {
|
|
8181
|
+
return { editable: false, reason: `\u0625\u063A\u0644\u0627\u0642 \u0628\u064A\u0626\u0629 \u0631\u064A\u0627\u0636\u064A\u0629 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645 \u062D\u0627\u0644\u064A\u0627: ${node.closing}` };
|
|
8182
|
+
}
|
|
8183
|
+
const rowCells = node.lines.map(splitEnvLine);
|
|
8184
|
+
const rows = Math.max(1, rowCells.length);
|
|
8185
|
+
const columns = Math.max(1, ...rowCells.map((row) => row.length));
|
|
8186
|
+
const env = createGridEnvNode(parsed.envName, rows, columns, parsed.alignments);
|
|
8187
|
+
for (let rowIndex = 0; rowIndex < rows; rowIndex += 1) {
|
|
8188
|
+
const row = rowCells[rowIndex] ?? [];
|
|
8189
|
+
for (let columnIndex = 0; columnIndex < columns; columnIndex += 1) {
|
|
8190
|
+
const cell = chainToEditorChain(row[columnIndex] ?? new ChainNode());
|
|
8191
|
+
if (!cell.editable) {
|
|
8192
|
+
return cell;
|
|
8193
|
+
}
|
|
8194
|
+
env.matrixRows[rowIndex][columnIndex] = cell.chain;
|
|
8195
|
+
}
|
|
8196
|
+
}
|
|
8197
|
+
if (parsed.envName === "array") {
|
|
8198
|
+
env.columnAlignments = Array.from(
|
|
8199
|
+
{ length: columns },
|
|
8200
|
+
(_, index) => parsed.alignments?.[index] ?? "c"
|
|
8201
|
+
);
|
|
8202
|
+
}
|
|
8203
|
+
if (isMatrixEnvName(parsed.envName)) {
|
|
8204
|
+
env.matrixStyle = parsed.envName;
|
|
8205
|
+
}
|
|
8206
|
+
const scripts = attachScripts(node, env);
|
|
8207
|
+
return scripts ?? { editable: true, node: env };
|
|
8208
|
+
}
|
|
8209
|
+
function charFromTextLikeCommand(node) {
|
|
8210
|
+
const commandFont = COMMAND_FONT_MAP[node.name];
|
|
8211
|
+
if (commandFont === void 0) {
|
|
8212
|
+
return null;
|
|
8213
|
+
}
|
|
8214
|
+
if (node.optionalArgs.length > 0 || node.mandatoryArgs.length !== 1) {
|
|
8215
|
+
return null;
|
|
8216
|
+
}
|
|
8217
|
+
const arg = node.mandatoryArgs[0];
|
|
8218
|
+
if (arg.chain.length !== 1) {
|
|
8219
|
+
return null;
|
|
8220
|
+
}
|
|
8221
|
+
const child = arg.chain[0];
|
|
8222
|
+
if (child instanceof CommandNode) {
|
|
8223
|
+
const nested = charFromTextLikeCommand(child);
|
|
8224
|
+
if (!nested?.editable) {
|
|
8225
|
+
return null;
|
|
8226
|
+
}
|
|
8227
|
+
if (commandFont !== "infer") {
|
|
8228
|
+
nested.node.characterFont = commandFont;
|
|
8229
|
+
}
|
|
8230
|
+
const scripts2 = attachScripts(node, nested.node);
|
|
8231
|
+
return scripts2 ?? nested;
|
|
8232
|
+
}
|
|
8233
|
+
if (!(child instanceof CharNode)) {
|
|
8234
|
+
return null;
|
|
8235
|
+
}
|
|
8236
|
+
const normalized = normalizeCharImportExpr(child.expr);
|
|
8237
|
+
const characterFont = commandFont === "infer" ? normalized.characterFont : commandFont;
|
|
8238
|
+
const editorNode = createEditorNode("char", normalized.expr);
|
|
8239
|
+
if (characterFont !== "default") {
|
|
8240
|
+
editorNode.characterFont = characterFont;
|
|
8241
|
+
}
|
|
8242
|
+
const scripts = attachScripts(node, editorNode);
|
|
8243
|
+
return scripts ?? { editable: true, node: editorNode };
|
|
8244
|
+
}
|
|
8245
|
+
function commandToEditorNode(node) {
|
|
8246
|
+
if (node.name === "\\frac" && node.mandatoryArgs.length >= 2) {
|
|
8247
|
+
const frac = createFracNode();
|
|
8248
|
+
const numerator = chainToEditorChain(node.mandatoryArgs[0]);
|
|
8249
|
+
const denominator = chainToEditorChain(node.mandatoryArgs[1]);
|
|
8250
|
+
if (!numerator.editable) {
|
|
8251
|
+
return numerator;
|
|
8252
|
+
}
|
|
8253
|
+
if (!denominator.editable) {
|
|
8254
|
+
return denominator;
|
|
8255
|
+
}
|
|
8256
|
+
frac.numerator = numerator.chain;
|
|
8257
|
+
frac.denominator = denominator.chain;
|
|
8258
|
+
const scripts = attachScripts(node, frac);
|
|
8259
|
+
if (scripts) {
|
|
8260
|
+
return scripts;
|
|
8261
|
+
}
|
|
8262
|
+
return { editable: true, node: frac };
|
|
8263
|
+
}
|
|
8264
|
+
if ((node.name === "\\sqrt" || node.name === "\\arabsqrt" || node.name === "\\arsqrt") && node.mandatoryArgs.length >= 1) {
|
|
8265
|
+
const sqrt = createSqrtNode();
|
|
8266
|
+
const radicand = chainToEditorChain(node.mandatoryArgs[0]);
|
|
8267
|
+
if (!radicand.editable) {
|
|
8268
|
+
return radicand;
|
|
8269
|
+
}
|
|
8270
|
+
sqrt.radicand = radicand.chain;
|
|
8271
|
+
if (node.optionalArgs[0]) {
|
|
8272
|
+
const rootIndex = chainToEditorChain(node.optionalArgs[0]);
|
|
8273
|
+
if (!rootIndex.editable) {
|
|
8274
|
+
return rootIndex;
|
|
8275
|
+
}
|
|
8276
|
+
sqrt.rootIndex = rootIndex.chain;
|
|
8277
|
+
}
|
|
8278
|
+
const scripts = attachScripts(node, sqrt);
|
|
8279
|
+
if (scripts) {
|
|
8280
|
+
return scripts;
|
|
8281
|
+
}
|
|
8282
|
+
return { editable: true, node: sqrt };
|
|
8283
|
+
}
|
|
8284
|
+
if (node.name === "\\overset" && node.mandatoryArgs.length >= 2) {
|
|
8285
|
+
const overset = createOversetNode();
|
|
8286
|
+
const overExpr = chainToEditorChain(node.mandatoryArgs[0]);
|
|
8287
|
+
const baseExpr = chainToEditorChain(node.mandatoryArgs[1]);
|
|
8288
|
+
if (!overExpr.editable) {
|
|
8289
|
+
return overExpr;
|
|
8290
|
+
}
|
|
8291
|
+
if (!baseExpr.editable) {
|
|
8292
|
+
return baseExpr;
|
|
8293
|
+
}
|
|
8294
|
+
overset.overExpr = overExpr.chain;
|
|
8295
|
+
overset.baseExpr = baseExpr.chain;
|
|
8296
|
+
const scripts = attachScripts(node, overset);
|
|
8297
|
+
if (scripts) {
|
|
8298
|
+
return scripts;
|
|
8299
|
+
}
|
|
8300
|
+
return { editable: true, node: overset };
|
|
8301
|
+
}
|
|
8302
|
+
if (node.name === "\\underset" && node.mandatoryArgs.length >= 2) {
|
|
8303
|
+
const underset = createUndersetNode();
|
|
8304
|
+
const underExpr = chainToEditorChain(node.mandatoryArgs[0]);
|
|
8305
|
+
const baseExpr = chainToEditorChain(node.mandatoryArgs[1]);
|
|
8306
|
+
if (!underExpr.editable) {
|
|
8307
|
+
return underExpr;
|
|
8308
|
+
}
|
|
8309
|
+
if (!baseExpr.editable) {
|
|
8310
|
+
return baseExpr;
|
|
8311
|
+
}
|
|
8312
|
+
underset.underExpr = underExpr.chain;
|
|
8313
|
+
underset.baseExpr = baseExpr.chain;
|
|
8314
|
+
const scripts = attachScripts(node, underset);
|
|
8315
|
+
if (scripts) {
|
|
8316
|
+
return scripts;
|
|
8317
|
+
}
|
|
8318
|
+
return { editable: true, node: underset };
|
|
8319
|
+
}
|
|
8320
|
+
const accentId = accentCommandIdFromTex(node.name);
|
|
8321
|
+
if (accentId && node.mandatoryArgs.length >= 1) {
|
|
8322
|
+
const accent = createAccentNode(accentId);
|
|
8323
|
+
const baseExpr = chainToEditorChain(node.mandatoryArgs[0]);
|
|
8324
|
+
if (!baseExpr.editable) {
|
|
8325
|
+
return baseExpr;
|
|
8326
|
+
}
|
|
8327
|
+
accent.baseExpr = baseExpr.chain;
|
|
8328
|
+
const scripts = attachScripts(node, accent);
|
|
8329
|
+
if (scripts) {
|
|
8330
|
+
return scripts;
|
|
8331
|
+
}
|
|
8332
|
+
return { editable: true, node: accent };
|
|
8333
|
+
}
|
|
8334
|
+
const atomicId = commandIdForTex(node.name);
|
|
8335
|
+
if (atomicId && node.optionalArgs.length === 0 && node.mandatoryArgs.length === 0) {
|
|
8336
|
+
const atomic = createEditorNode("atomicCommand", atomicId);
|
|
8337
|
+
const scripts = attachScripts(node, atomic);
|
|
8338
|
+
if (scripts) {
|
|
8339
|
+
return scripts;
|
|
8340
|
+
}
|
|
8341
|
+
return { editable: true, node: atomic };
|
|
8342
|
+
}
|
|
8343
|
+
const operatorId = operatorCommandIdForTex(node.name);
|
|
8344
|
+
if (operatorId && node.optionalArgs.length === 0 && node.mandatoryArgs.length === 0) {
|
|
8345
|
+
const atomicOperator = createEditorNode("atomicOperatorCommand", operatorId);
|
|
8346
|
+
const scripts = attachScripts(node, atomicOperator);
|
|
8347
|
+
if (scripts) {
|
|
8348
|
+
return scripts;
|
|
8349
|
+
}
|
|
8350
|
+
return { editable: true, node: atomicOperator };
|
|
8351
|
+
}
|
|
8352
|
+
const textLike = charFromTextLikeCommand(node);
|
|
8353
|
+
if (textLike) {
|
|
8354
|
+
return textLike;
|
|
8355
|
+
}
|
|
8356
|
+
return { editable: false, reason: `\u0623\u0645\u0631 \u0631\u064A\u0627\u0636\u064A \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645 \u062D\u0627\u0644\u064A\u0627: ${node.name}` };
|
|
8357
|
+
}
|
|
8358
|
+
function astNodeToEditorNode(node) {
|
|
8359
|
+
if (node instanceof CharNode) {
|
|
8360
|
+
const normalized = normalizeCharImportExpr(node.expr);
|
|
8361
|
+
const editorNode = createEditorNode("char", normalized.expr);
|
|
8362
|
+
if (normalized.characterFont !== "default") {
|
|
8363
|
+
editorNode.characterFont = normalized.characterFont;
|
|
8364
|
+
}
|
|
8365
|
+
const scripts = attachScripts(node, editorNode);
|
|
8366
|
+
return scripts ?? { editable: true, node: editorNode };
|
|
8367
|
+
}
|
|
8368
|
+
if (node instanceof NumberNode) {
|
|
8369
|
+
const editorNode = createEditorNode("number", node.expr);
|
|
8370
|
+
const scripts = attachScripts(node, editorNode);
|
|
8371
|
+
return scripts ?? { editable: true, node: editorNode };
|
|
8372
|
+
}
|
|
8373
|
+
if (node instanceof OperatorNode) {
|
|
8374
|
+
return { editable: true, node: createEditorNode("operator", node.expr) };
|
|
8375
|
+
}
|
|
8376
|
+
if (node instanceof DelimiterNode) {
|
|
8377
|
+
const editorNode = createDelimiterNode(node.leftDelimExpr, node.rightDelimExpr);
|
|
8378
|
+
const inner = chainToEditorChain(node.innerExpr);
|
|
8379
|
+
if (!inner.editable) {
|
|
8380
|
+
return inner;
|
|
8381
|
+
}
|
|
8382
|
+
editorNode.innerExpr = inner.chain;
|
|
8383
|
+
const scripts = attachScripts(node, editorNode);
|
|
8384
|
+
return scripts ?? { editable: true, node: editorNode };
|
|
8385
|
+
}
|
|
8386
|
+
if (node instanceof CommandNode) {
|
|
8387
|
+
return commandToEditorNode(node);
|
|
8388
|
+
}
|
|
8389
|
+
if (node instanceof EnvNode) {
|
|
8390
|
+
return envToEditorNode(node);
|
|
8391
|
+
}
|
|
8392
|
+
return { editable: false, reason: `\u0639\u0642\u062F\u0629 \u0631\u064A\u0627\u0636\u064A\u0629 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645\u0629 \u062D\u0627\u0644\u064A\u0627: ${node.nodeType}` };
|
|
8393
|
+
}
|
|
8394
|
+
function chainToEditorChain(chain) {
|
|
8395
|
+
const nodes = [];
|
|
8396
|
+
for (const astNode of chain.chain) {
|
|
8397
|
+
const converted = astNodeToEditorNode(astNode);
|
|
8398
|
+
if (!converted.editable) {
|
|
8399
|
+
return converted;
|
|
8400
|
+
}
|
|
8401
|
+
nodes.push(converted.node);
|
|
8402
|
+
}
|
|
8403
|
+
return { editable: true, chain: createEditorChain(nodes) };
|
|
8404
|
+
}
|
|
8405
|
+
function mathObjectToEditorSession(math) {
|
|
8406
|
+
if (math.lines.length !== 1) {
|
|
8407
|
+
return { editable: false, reason: "\u062A\u062D\u0631\u064A\u0631 \u0627\u0644\u0645\u0639\u0627\u062F\u0644\u0627\u062A \u0645\u062A\u0639\u062F\u062F\u0629 \u0627\u0644\u0623\u0633\u0637\u0631 \u062F\u0627\u062E\u0644 \u0627\u0644\u0645\u0633\u062A\u0646\u062F \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645 \u0628\u0639\u062F" };
|
|
8408
|
+
}
|
|
8409
|
+
const english = chainToEditorChain(math.lines[0]);
|
|
8410
|
+
if (!english.editable) {
|
|
8411
|
+
return english;
|
|
8412
|
+
}
|
|
8413
|
+
const arabic = cloneChainWithFreshIds(english.chain);
|
|
8414
|
+
const session = createEditorSession(english.chain, arabic, "english");
|
|
8415
|
+
session.sync = buildInitialSyncMap(session.englishTree, session.arabicTree);
|
|
8416
|
+
return { editable: true, session: cloneEditorSession(session) };
|
|
8417
|
+
}
|
|
8418
|
+
function attachAstScripts(editorNode, astNode) {
|
|
8419
|
+
if (editorNode.superscript) {
|
|
8420
|
+
const sup = editorChainToAstChain(editorNode.superscript);
|
|
8421
|
+
if (!sup.ok) {
|
|
8422
|
+
return sup;
|
|
8423
|
+
}
|
|
8424
|
+
astNode.superscript = sup.chain;
|
|
8425
|
+
}
|
|
8426
|
+
if (editorNode.subscript) {
|
|
8427
|
+
const sub = editorChainToAstChain(editorNode.subscript);
|
|
8428
|
+
if (!sub.ok) {
|
|
8429
|
+
return sub;
|
|
8430
|
+
}
|
|
8431
|
+
astNode.subscript = sub.chain;
|
|
8432
|
+
}
|
|
8433
|
+
return null;
|
|
8434
|
+
}
|
|
8435
|
+
function editorEnvOpening(node) {
|
|
8436
|
+
const envName = node.envName ?? node.matrixStyle;
|
|
8437
|
+
if (!envName) {
|
|
8438
|
+
return null;
|
|
8439
|
+
}
|
|
8440
|
+
if (envName === "array") {
|
|
8441
|
+
const spec = (node.columnAlignments ?? []).slice(0, node.matrixRows?.[0]?.length ?? 0).join("") || "c";
|
|
8442
|
+
return { opening: `\\begin{array}{${spec}}`, closing: "\\end{array}" };
|
|
8443
|
+
}
|
|
8444
|
+
return { opening: `\\begin{${envName}}`, closing: `\\end{${envName}}` };
|
|
8445
|
+
}
|
|
8446
|
+
function editorEnvToAstNode(node) {
|
|
8447
|
+
const wrapper = editorEnvOpening(node);
|
|
8448
|
+
if (!wrapper || !node.matrixRows) {
|
|
8449
|
+
return { ok: false, reason: "\u0628\u064A\u0626\u0629 \u0631\u064A\u0627\u0636\u064A\u0629 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645\u0629 \u062D\u0627\u0644\u064A\u0627" };
|
|
8450
|
+
}
|
|
8451
|
+
const lines = [];
|
|
8452
|
+
for (const row of node.matrixRows) {
|
|
8453
|
+
const lineNodes = [];
|
|
8454
|
+
for (let columnIndex = 0; columnIndex < row.length; columnIndex += 1) {
|
|
8455
|
+
if (columnIndex > 0) {
|
|
8456
|
+
lineNodes.push(new OperatorNode("&"));
|
|
8457
|
+
}
|
|
8458
|
+
const cell = editorChainToAstChain(row[columnIndex]);
|
|
8459
|
+
if (!cell.ok) {
|
|
8460
|
+
return cell;
|
|
8461
|
+
}
|
|
8462
|
+
lineNodes.push(...cell.chain.chain);
|
|
8463
|
+
}
|
|
8464
|
+
lines.push(new ChainNode(lineNodes));
|
|
8465
|
+
}
|
|
8466
|
+
const env = new EnvNode(wrapper.opening, lines, wrapper.closing);
|
|
8467
|
+
const scripts = attachAstScripts(node, env);
|
|
8468
|
+
return scripts ?? { ok: true, node: env };
|
|
8469
|
+
}
|
|
8470
|
+
function accentChainForExport(accent) {
|
|
8471
|
+
if (!accent) {
|
|
8472
|
+
return { ok: true, chain: new ChainNode([]) };
|
|
8473
|
+
}
|
|
8474
|
+
return editorChainToAstChain(accent);
|
|
8475
|
+
}
|
|
8476
|
+
function nodeFromAccentBase(command, accent, base) {
|
|
8477
|
+
if (accent.chain.length > 0) {
|
|
8478
|
+
return new CommandNode(command, [], [accent, base]);
|
|
8479
|
+
}
|
|
8480
|
+
if (base.chain.length === 1) {
|
|
8481
|
+
return base.chain[0];
|
|
8482
|
+
}
|
|
8483
|
+
return new DelimiterNode("", base, "");
|
|
8484
|
+
}
|
|
8485
|
+
function editorNodeToAstNode(node) {
|
|
8486
|
+
let astNode;
|
|
8487
|
+
if (node.kind === "char") {
|
|
8488
|
+
astNode = charEditorNodeToAstNode(node);
|
|
8489
|
+
} else if (node.kind === "number") {
|
|
8490
|
+
astNode = new NumberNode(node.expr);
|
|
8491
|
+
} else if (node.kind === "operator") {
|
|
8492
|
+
astNode = new OperatorNode(node.expr);
|
|
8493
|
+
} else if (node.kind === "delimiter" && node.innerExpr) {
|
|
8494
|
+
const inner = editorChainToAstChain(node.innerExpr);
|
|
8495
|
+
if (!inner.ok) {
|
|
8496
|
+
return inner;
|
|
8497
|
+
}
|
|
8498
|
+
astNode = new DelimiterNode(node.leftDelimExpr, inner.chain, node.rightDelimExpr);
|
|
8499
|
+
} else if (node.kind === "frac" && node.numerator && node.denominator) {
|
|
8500
|
+
const numerator = editorChainToAstChain(node.numerator);
|
|
8501
|
+
const denominator = editorChainToAstChain(node.denominator);
|
|
8502
|
+
if (!numerator.ok) {
|
|
8503
|
+
return numerator;
|
|
8504
|
+
}
|
|
8505
|
+
if (!denominator.ok) {
|
|
8506
|
+
return denominator;
|
|
8507
|
+
}
|
|
8508
|
+
astNode = new CommandNode("\\frac", [], [numerator.chain, denominator.chain]);
|
|
8509
|
+
} else if (node.kind === "sqrt" && node.radicand) {
|
|
8510
|
+
const radicand = editorChainToAstChain(node.radicand);
|
|
8511
|
+
if (!radicand.ok) {
|
|
8512
|
+
return radicand;
|
|
8513
|
+
}
|
|
8514
|
+
const optionalArgs = [];
|
|
8515
|
+
if (node.rootIndex && node.rootIndex.nodes.length > 0) {
|
|
8516
|
+
const rootIndex = editorChainToAstChain(node.rootIndex);
|
|
8517
|
+
if (!rootIndex.ok) {
|
|
8518
|
+
return rootIndex;
|
|
8519
|
+
}
|
|
8520
|
+
optionalArgs.push(rootIndex.chain);
|
|
8521
|
+
}
|
|
8522
|
+
astNode = new CommandNode("\\sqrt", optionalArgs, [radicand.chain]);
|
|
8523
|
+
} else if (node.kind === "overset" && node.baseExpr) {
|
|
8524
|
+
const accent = accentChainForExport(node.overExpr);
|
|
8525
|
+
if (!accent.ok) {
|
|
8526
|
+
return accent;
|
|
8527
|
+
}
|
|
8528
|
+
const baseExpr = editorChainToAstChain(node.baseExpr);
|
|
8529
|
+
if (!baseExpr.ok) {
|
|
8530
|
+
return baseExpr;
|
|
8531
|
+
}
|
|
8532
|
+
astNode = nodeFromAccentBase("\\overset", accent.chain, baseExpr.chain);
|
|
8533
|
+
} else if (node.kind === "underset" && node.baseExpr) {
|
|
8534
|
+
const accent = accentChainForExport(node.underExpr);
|
|
8535
|
+
if (!accent.ok) {
|
|
8536
|
+
return accent;
|
|
8537
|
+
}
|
|
8538
|
+
const baseExpr = editorChainToAstChain(node.baseExpr);
|
|
8539
|
+
if (!baseExpr.ok) {
|
|
8540
|
+
return baseExpr;
|
|
8541
|
+
}
|
|
8542
|
+
astNode = nodeFromAccentBase("\\underset", accent.chain, baseExpr.chain);
|
|
8543
|
+
} else if (node.kind === "accent" && node.baseExpr) {
|
|
8544
|
+
const tex = accentCommandSpec(node.expr)?.englishTex;
|
|
8545
|
+
if (!tex) {
|
|
8546
|
+
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}` };
|
|
8547
|
+
}
|
|
8548
|
+
const baseExpr = editorChainToAstChain(node.baseExpr);
|
|
8549
|
+
if (!baseExpr.ok) {
|
|
8550
|
+
return baseExpr;
|
|
8551
|
+
}
|
|
8552
|
+
astNode = new CommandNode(tex, [], [baseExpr.chain]);
|
|
8553
|
+
} else if (node.kind === "atomicCommand") {
|
|
8554
|
+
const tex = atomicCommandSpec(node.expr)?.englishTex;
|
|
8555
|
+
if (!tex) {
|
|
8556
|
+
return { ok: false, reason: `\u0623\u0645\u0631 \u0631\u064A\u0627\u0636\u064A \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645 \u062D\u0627\u0644\u064A\u0627: ${node.expr}` };
|
|
8557
|
+
}
|
|
8558
|
+
astNode = new CommandNode(tex);
|
|
8559
|
+
} else if (node.kind === "atomicOperatorCommand") {
|
|
8560
|
+
const tex = atomicOperatorCommandSpec(node.expr)?.Tex;
|
|
8561
|
+
if (!tex) {
|
|
8562
|
+
return { ok: false, reason: `\u0631\u0645\u0632 \u0631\u064A\u0627\u0636\u064A \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645 \u062D\u0627\u0644\u064A\u0627: ${node.expr}` };
|
|
8563
|
+
}
|
|
8564
|
+
astNode = new CommandNode(tex);
|
|
8565
|
+
} else if (node.kind === "env") {
|
|
8566
|
+
return editorEnvToAstNode(node);
|
|
8567
|
+
} else {
|
|
8568
|
+
return { ok: false, reason: `\u0639\u0642\u062F\u0629 \u0631\u064A\u0627\u0636\u064A\u0629 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645\u0629 \u062D\u0627\u0644\u064A\u0627: ${node.kind}` };
|
|
8569
|
+
}
|
|
8570
|
+
const scripts = attachAstScripts(node, astNode);
|
|
8571
|
+
return scripts ?? { ok: true, node: astNode };
|
|
8572
|
+
}
|
|
8573
|
+
function editorChainToAstChain(chain) {
|
|
8574
|
+
const nodes = [];
|
|
8575
|
+
for (const editorNode of chain.nodes) {
|
|
8576
|
+
const converted = editorNodeToAstNode(editorNode);
|
|
8577
|
+
if (!converted.ok) {
|
|
8578
|
+
return converted;
|
|
8579
|
+
}
|
|
8580
|
+
nodes.push(converted.node);
|
|
8581
|
+
}
|
|
8582
|
+
return { ok: true, chain: new ChainNode(nodes) };
|
|
8583
|
+
}
|
|
8584
|
+
function mathNodeFromEditorSession(session, mathMode = "$", closing = "$") {
|
|
8585
|
+
const converted = editorChainToAstChain(session.englishTree);
|
|
8586
|
+
if (!converted.ok) {
|
|
8587
|
+
return converted;
|
|
8588
|
+
}
|
|
8589
|
+
return {
|
|
8590
|
+
ok: true,
|
|
8591
|
+
math: {
|
|
8592
|
+
nodeType: "MathObject",
|
|
8593
|
+
mathMode,
|
|
8594
|
+
lines: [converted.chain],
|
|
8595
|
+
closing
|
|
8596
|
+
}
|
|
8597
|
+
};
|
|
8598
|
+
}
|
|
8599
|
+
|
|
8600
|
+
// src/debugJson.ts
|
|
8601
|
+
function lineColumnForPosition(text, position) {
|
|
8602
|
+
const before = text.slice(0, Math.max(0, position));
|
|
8603
|
+
const lines = before.split("\n");
|
|
8604
|
+
return {
|
|
8605
|
+
line: lines.length,
|
|
8606
|
+
column: (lines[lines.length - 1]?.length ?? 0) + 1
|
|
8607
|
+
};
|
|
8608
|
+
}
|
|
8609
|
+
function parseJsonDebugInput(text) {
|
|
8610
|
+
try {
|
|
8611
|
+
return { ok: true, value: JSON.parse(text) };
|
|
8612
|
+
} catch (error) {
|
|
8613
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8614
|
+
const positionMatch = message.match(/position\s+(\d+)/i);
|
|
8615
|
+
if (positionMatch) {
|
|
8616
|
+
const position = Number(positionMatch[1]);
|
|
8617
|
+
if (Number.isFinite(position)) {
|
|
8618
|
+
const location = lineColumnForPosition(text, position);
|
|
8619
|
+
return { ok: false, error: `Invalid JSON at line ${String(location.line)}, column ${String(location.column)}: ${message}` };
|
|
8620
|
+
}
|
|
8621
|
+
}
|
|
8622
|
+
return { ok: false, error: `Invalid JSON: ${message}` };
|
|
8623
|
+
}
|
|
8624
|
+
}
|
|
8625
|
+
|
|
7439
8626
|
// src/react/ButexEditor.tsx
|
|
7440
8627
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
7441
8628
|
var DIGIT_FORM_OPTIONS = [
|
|
@@ -7551,6 +8738,7 @@ ${latex || messages.empty}`;
|
|
|
7551
8738
|
var ButexEditor = (0, import_react.forwardRef)(
|
|
7552
8739
|
function ButexEditor2({ className, debug = false, defaultSide, uiLocale = "ar", initialSession, onSessionChange }, ref) {
|
|
7553
8740
|
const messages = equationEditorMessages(uiLocale);
|
|
8741
|
+
const debugEnabled = debug || typeof window !== "undefined" && new URLSearchParams(window.location.search).get("debug") === "1";
|
|
7554
8742
|
const wrapperRef = (0, import_react.useRef)(null);
|
|
7555
8743
|
const surfaceRef = (0, import_react.useRef)(null);
|
|
7556
8744
|
const inputRef = (0, import_react.useRef)(null);
|
|
@@ -7568,7 +8756,7 @@ var ButexEditor = (0, import_react.forwardRef)(
|
|
|
7568
8756
|
const digitFormBtnRef = (0, import_react.useRef)(null);
|
|
7569
8757
|
const runtimeRef = (0, import_react.useRef)(null);
|
|
7570
8758
|
const debugRef = (0, import_react.useRef)(debug);
|
|
7571
|
-
debugRef.current =
|
|
8759
|
+
debugRef.current = debugEnabled;
|
|
7572
8760
|
const uiLocaleRef = (0, import_react.useRef)(uiLocale);
|
|
7573
8761
|
uiLocaleRef.current = uiLocale;
|
|
7574
8762
|
const onSessionChangeRef = (0, import_react.useRef)(onSessionChange);
|
|
@@ -7576,6 +8764,9 @@ var ButexEditor = (0, import_react.forwardRef)(
|
|
|
7576
8764
|
const debugBodyHiddenRef = (0, import_react.useRef)(false);
|
|
7577
8765
|
const [debugBodyHidden, setDebugBodyHidden] = (0, import_react.useState)(false);
|
|
7578
8766
|
debugBodyHiddenRef.current = debugBodyHidden;
|
|
8767
|
+
const [debugImportOpen, setDebugImportOpen] = (0, import_react.useState)(false);
|
|
8768
|
+
const [debugImportText, setDebugImportText] = (0, import_react.useState)("");
|
|
8769
|
+
const [debugImportError, setDebugImportError] = (0, import_react.useState)("");
|
|
7579
8770
|
const [digitMenuOpen, setDigitMenuOpen] = (0, import_react.useState)(false);
|
|
7580
8771
|
const [characterFontMenuOpen, setCharacterFontMenuOpen] = (0, import_react.useState)(false);
|
|
7581
8772
|
const [delimiterMenuOpen, setDelimiterMenuOpen] = (0, import_react.useState)(false);
|
|
@@ -7656,6 +8847,54 @@ ${arabic || currentMessages.empty}`;
|
|
|
7656
8847
|
}, []);
|
|
7657
8848
|
const updatePreviewRef = (0, import_react.useRef)(updatePreview);
|
|
7658
8849
|
updatePreviewRef.current = updatePreview;
|
|
8850
|
+
async function copyDebugText(text) {
|
|
8851
|
+
try {
|
|
8852
|
+
await navigator.clipboard.writeText(text);
|
|
8853
|
+
} catch {
|
|
8854
|
+
}
|
|
8855
|
+
}
|
|
8856
|
+
function currentMathObjectJsonText() {
|
|
8857
|
+
const session = runtimeRef.current?.getSession();
|
|
8858
|
+
if (!session) {
|
|
8859
|
+
return "";
|
|
8860
|
+
}
|
|
8861
|
+
const math = mathNodeFromEditorSession(session);
|
|
8862
|
+
if (!math.ok) {
|
|
8863
|
+
return "";
|
|
8864
|
+
}
|
|
8865
|
+
return JSON.stringify(toMathObjectJson(math.math), null, 2);
|
|
8866
|
+
}
|
|
8867
|
+
function openDebugMathObjectImport() {
|
|
8868
|
+
setDebugImportText(currentMathObjectJsonText());
|
|
8869
|
+
setDebugImportError("");
|
|
8870
|
+
setDebugImportOpen(true);
|
|
8871
|
+
}
|
|
8872
|
+
function applyDebugMathObjectImport() {
|
|
8873
|
+
const parsed = parseJsonDebugInput(debugImportText);
|
|
8874
|
+
if (!parsed.ok) {
|
|
8875
|
+
setDebugImportError(parsed.error);
|
|
8876
|
+
return;
|
|
8877
|
+
}
|
|
8878
|
+
try {
|
|
8879
|
+
const math = fromMathObjectJson(parsed.value, activeEditorSide);
|
|
8880
|
+
const result = mathObjectToEditorSession(math);
|
|
8881
|
+
if (!result.editable) {
|
|
8882
|
+
setDebugImportError(result.reason);
|
|
8883
|
+
return;
|
|
8884
|
+
}
|
|
8885
|
+
const next = { ...result.session, activeSide: activeEditorSide };
|
|
8886
|
+
runtimeRef.current?.setSession(next);
|
|
8887
|
+
setSelectedDigitForm(next.currentDigitForm ?? "western");
|
|
8888
|
+
setSelectedCharacterFont(next.currentCharacterFont ?? "default");
|
|
8889
|
+
setActiveEditorSide(next.activeSide);
|
|
8890
|
+
onSessionChangeRef.current?.(next);
|
|
8891
|
+
setDebugImportError("");
|
|
8892
|
+
setDebugImportOpen(false);
|
|
8893
|
+
void updatePreviewRef.current(next);
|
|
8894
|
+
} catch (importError) {
|
|
8895
|
+
setDebugImportError(importError instanceof Error ? importError.message : String(importError));
|
|
8896
|
+
}
|
|
8897
|
+
}
|
|
7659
8898
|
(0, import_react.useEffect)(() => {
|
|
7660
8899
|
injectWidgetChromeCss();
|
|
7661
8900
|
injectBuTeXEditorStyles(typeof document !== "undefined" ? document : void 0);
|
|
@@ -8816,7 +10055,7 @@ ${arabic || currentMessages.empty}`;
|
|
|
8816
10055
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: renderErrorRef, className: "error", hidden: true })
|
|
8817
10056
|
] }),
|
|
8818
10057
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: "panel panel-preview", "aria-label": messages.renderPreview, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: mathOutputRef, className: "preview-box" }) }),
|
|
8819
|
-
|
|
10058
|
+
debugEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "panel", children: [
|
|
8820
10059
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dev-strip", children: [
|
|
8821
10060
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dev-badge", children: messages.development }),
|
|
8822
10061
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: latexLinesRef, className: "ascii" }),
|
|
@@ -8824,6 +10063,8 @@ ${arabic || currentMessages.empty}`;
|
|
|
8824
10063
|
] }),
|
|
8825
10064
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: 12 }, children: [
|
|
8826
10065
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "debug-head", children: [
|
|
10066
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => void copyDebugText(currentMathObjectJsonText()), children: "Copy MathObject JSON" }),
|
|
10067
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", "aria-expanded": debugImportOpen, onClick: openDebugMathObjectImport, children: "Import MathObject JSON" }),
|
|
8827
10068
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
8828
10069
|
"button",
|
|
8829
10070
|
{
|
|
@@ -8859,6 +10100,35 @@ ${arabic || currentMessages.empty}`;
|
|
|
8859
10100
|
}
|
|
8860
10101
|
)
|
|
8861
10102
|
] }),
|
|
10103
|
+
debugImportOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "debug-json-import", children: [
|
|
10104
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10105
|
+
"textarea",
|
|
10106
|
+
{
|
|
10107
|
+
value: debugImportText,
|
|
10108
|
+
"aria-label": "Import MathObject JSON",
|
|
10109
|
+
spellCheck: false,
|
|
10110
|
+
onChange: (event) => {
|
|
10111
|
+
setDebugImportText(event.currentTarget.value);
|
|
10112
|
+
setDebugImportError("");
|
|
10113
|
+
}
|
|
10114
|
+
}
|
|
10115
|
+
),
|
|
10116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "debug-head", children: [
|
|
10117
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: applyDebugMathObjectImport, children: "Apply" }),
|
|
10118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10119
|
+
"button",
|
|
10120
|
+
{
|
|
10121
|
+
type: "button",
|
|
10122
|
+
onClick: () => {
|
|
10123
|
+
setDebugImportOpen(false);
|
|
10124
|
+
setDebugImportError("");
|
|
10125
|
+
},
|
|
10126
|
+
children: "Cancel"
|
|
10127
|
+
}
|
|
10128
|
+
)
|
|
10129
|
+
] }),
|
|
10130
|
+
debugImportError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "debug-json-error", children: debugImportError }) : null
|
|
10131
|
+
] }) : null,
|
|
8862
10132
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: debugLogRef, className: "debug-log" })
|
|
8863
10133
|
] })
|
|
8864
10134
|
] }) : null
|