ed-mathml2tex 0.0.8 → 0.0.9
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/lib/mathml2latex.browser.cjs.js +55 -70
- package/lib/mathml2latex.browser.es.js +55 -70
- package/lib/mathml2latex.browser.umd.js +55 -70
- package/lib/mathml2latex.cjs.js +55 -70
- package/lib/mathml2latex.es.js +55 -70
- package/lib/mathml2latex.umd.js +55 -70
- package/package.json +1 -1
|
@@ -147,7 +147,9 @@ const NodeTool = {
|
|
|
147
147
|
return node.children;
|
|
148
148
|
},
|
|
149
149
|
getNodeName: function(node) {
|
|
150
|
-
|
|
150
|
+
if (!node) return '';
|
|
151
|
+
const localName = node.localName || node.nodeName;
|
|
152
|
+
return localName ? localName.toLowerCase() : '';
|
|
151
153
|
},
|
|
152
154
|
getNodeText: function(node) {
|
|
153
155
|
return node.textContent;
|
|
@@ -704,9 +706,9 @@ function parseLeaf(node) {
|
|
|
704
706
|
function parseOperator(node) {
|
|
705
707
|
let it = NodeTool.getNodeText(node).trim();
|
|
706
708
|
|
|
707
|
-
// Special case for arrow (→)
|
|
709
|
+
// Special case for arrow (→) with proper spacing
|
|
708
710
|
if (it === "→") {
|
|
709
|
-
return "\\rightarrow";
|
|
711
|
+
return " \\rightarrow "; // Add spaces around arrow
|
|
710
712
|
}
|
|
711
713
|
|
|
712
714
|
it = MathSymbol.parseOperator(it);
|
|
@@ -833,7 +835,28 @@ function getRender(node) {
|
|
|
833
835
|
const nodeName = NodeTool.getNodeName(node);
|
|
834
836
|
switch(nodeName){
|
|
835
837
|
case 'msub':
|
|
836
|
-
render =
|
|
838
|
+
render = function(node, children) {
|
|
839
|
+
if (!children || children.length < 2) return '';
|
|
840
|
+
|
|
841
|
+
const base = parse(children[0]);
|
|
842
|
+
if (!base) return '';
|
|
843
|
+
|
|
844
|
+
const sub = children[1];
|
|
845
|
+
if (!sub) return base;
|
|
846
|
+
|
|
847
|
+
// Handle nested subscript with empty mrow
|
|
848
|
+
if (NodeTool.getNodeName(sub) === 'msub' &&
|
|
849
|
+
sub.firstChild &&
|
|
850
|
+
NodeTool.getNodeName(sub.firstChild) === 'mrow' &&
|
|
851
|
+
(!NodeTool.getNodeText(sub.firstChild) || NodeTool.getNodeText(sub.firstChild).trim() === '')) {
|
|
852
|
+
const lastChild = sub.lastChild;
|
|
853
|
+
if (!lastChild) return base;
|
|
854
|
+
return `${base}_${parse(lastChild)}`;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// Regular subscript
|
|
858
|
+
return `${base}_{${parse(sub)}}`;
|
|
859
|
+
};
|
|
837
860
|
break;
|
|
838
861
|
case 'msup':
|
|
839
862
|
render = getRender_default("@1^{@2}");
|
|
@@ -895,10 +918,32 @@ function getRender(node) {
|
|
|
895
918
|
|
|
896
919
|
function renderTable(node, children) {
|
|
897
920
|
const template = "\\begin{array}{l}@content\\end{array}";
|
|
898
|
-
|
|
921
|
+
// Remove extra backslash and add proper spacing
|
|
922
|
+
const render = getRender_joinSeparator(template, " \\\\ ");
|
|
899
923
|
return render(node, children);
|
|
900
924
|
}
|
|
901
925
|
|
|
926
|
+
function renderMover(node, children) {
|
|
927
|
+
// Check if children exists and has enough elements
|
|
928
|
+
if (!children || children.length < 2) return '';
|
|
929
|
+
|
|
930
|
+
const baseNode = children[0];
|
|
931
|
+
const overNode = children[1];
|
|
932
|
+
|
|
933
|
+
// Check if nodes exist before accessing
|
|
934
|
+
if (!baseNode || !overNode) return '';
|
|
935
|
+
|
|
936
|
+
const overText = NodeTool.getNodeText(overNode)?.trim() || '';
|
|
937
|
+
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
938
|
+
|
|
939
|
+
// Handle vector notation
|
|
940
|
+
if (overText === "→" && isAccent) {
|
|
941
|
+
return `\\vec{${parse(baseNode)}}`;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
return parse(baseNode);
|
|
945
|
+
}
|
|
946
|
+
|
|
902
947
|
function renderMfenced(node, children) {
|
|
903
948
|
const [open, close, separatorsStr] = [
|
|
904
949
|
NodeTool.getAttr(node, 'open', '('),
|
|
@@ -909,9 +954,10 @@ function renderMfenced(node, children) {
|
|
|
909
954
|
const parts = renderChildren(children);
|
|
910
955
|
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
911
956
|
|
|
912
|
-
// Handle
|
|
913
|
-
if (open === ''
|
|
914
|
-
|
|
957
|
+
// Handle system of equations with curly brace
|
|
958
|
+
if (open === '{') {
|
|
959
|
+
// If no closing brace specified, use \right.
|
|
960
|
+
return `\\left\\{${content}${close ? '\\right\\}' : '\\right.'}`;
|
|
915
961
|
}
|
|
916
962
|
|
|
917
963
|
// Handle absolute value notation
|
|
@@ -919,12 +965,7 @@ function renderMfenced(node, children) {
|
|
|
919
965
|
return `\\left|${content}\\right|`;
|
|
920
966
|
}
|
|
921
967
|
|
|
922
|
-
// Regular
|
|
923
|
-
if (open === '(' && close === ')') {
|
|
924
|
-
return `\\left(${content}\\right)`;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
// Default case
|
|
968
|
+
// Regular cases with proper closing
|
|
928
969
|
return `\\left${open}${content}\\right${close || '.'}`;
|
|
929
970
|
}
|
|
930
971
|
|
|
@@ -1003,62 +1044,6 @@ function renderMmultiscripts(node, children) {
|
|
|
1003
1044
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
1004
1045
|
}
|
|
1005
1046
|
|
|
1006
|
-
function renderMover(node, children) {
|
|
1007
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
1008
|
-
let result = undefined;
|
|
1009
|
-
|
|
1010
|
-
// Get the base node and check if it's a subscript or mrow
|
|
1011
|
-
const baseNode = children[0];
|
|
1012
|
-
const overNode = children[1];
|
|
1013
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1014
|
-
const isSubscript = nodeName === 'msub';
|
|
1015
|
-
const isMrow = nodeName === 'mrow';
|
|
1016
|
-
|
|
1017
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1018
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1019
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1020
|
-
return "\\rightarrow";
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
if (isSubscript) {
|
|
1024
|
-
// Handle case like n₂ with arrow
|
|
1025
|
-
const base = parse(baseNode);
|
|
1026
|
-
return `\\overrightarrow{${base}}`;
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
if (isMrow) {
|
|
1030
|
-
// Handle case like 0 with arrow
|
|
1031
|
-
const base = parse(baseNode);
|
|
1032
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1033
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1034
|
-
|
|
1035
|
-
if (overText === "→" && isAccent) {
|
|
1036
|
-
return `\\overrightarrow{${base}}`;
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
// Handle case where there is only an arrow with no base
|
|
1041
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1042
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1043
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1047
|
-
if (!result) {
|
|
1048
|
-
result = parse(nodes[i]);
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
const _overNode = nodes[i + 1];
|
|
1052
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1053
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1054
|
-
|
|
1055
|
-
if (overText === "→" && isAccent) {
|
|
1056
|
-
return `\\overrightarrow{${result}}`;
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
return result;
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
1047
|
function renderMunder(node, children){
|
|
1063
1048
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1064
1049
|
let result = undefined;
|
|
@@ -145,7 +145,9 @@ const NodeTool = {
|
|
|
145
145
|
return node.children;
|
|
146
146
|
},
|
|
147
147
|
getNodeName: function(node) {
|
|
148
|
-
|
|
148
|
+
if (!node) return '';
|
|
149
|
+
const localName = node.localName || node.nodeName;
|
|
150
|
+
return localName ? localName.toLowerCase() : '';
|
|
149
151
|
},
|
|
150
152
|
getNodeText: function(node) {
|
|
151
153
|
return node.textContent;
|
|
@@ -702,9 +704,9 @@ function parseLeaf(node) {
|
|
|
702
704
|
function parseOperator(node) {
|
|
703
705
|
let it = NodeTool.getNodeText(node).trim();
|
|
704
706
|
|
|
705
|
-
// Special case for arrow (→)
|
|
707
|
+
// Special case for arrow (→) with proper spacing
|
|
706
708
|
if (it === "→") {
|
|
707
|
-
return "\\rightarrow";
|
|
709
|
+
return " \\rightarrow "; // Add spaces around arrow
|
|
708
710
|
}
|
|
709
711
|
|
|
710
712
|
it = MathSymbol.parseOperator(it);
|
|
@@ -831,7 +833,28 @@ function getRender(node) {
|
|
|
831
833
|
const nodeName = NodeTool.getNodeName(node);
|
|
832
834
|
switch(nodeName){
|
|
833
835
|
case 'msub':
|
|
834
|
-
render =
|
|
836
|
+
render = function(node, children) {
|
|
837
|
+
if (!children || children.length < 2) return '';
|
|
838
|
+
|
|
839
|
+
const base = parse(children[0]);
|
|
840
|
+
if (!base) return '';
|
|
841
|
+
|
|
842
|
+
const sub = children[1];
|
|
843
|
+
if (!sub) return base;
|
|
844
|
+
|
|
845
|
+
// Handle nested subscript with empty mrow
|
|
846
|
+
if (NodeTool.getNodeName(sub) === 'msub' &&
|
|
847
|
+
sub.firstChild &&
|
|
848
|
+
NodeTool.getNodeName(sub.firstChild) === 'mrow' &&
|
|
849
|
+
(!NodeTool.getNodeText(sub.firstChild) || NodeTool.getNodeText(sub.firstChild).trim() === '')) {
|
|
850
|
+
const lastChild = sub.lastChild;
|
|
851
|
+
if (!lastChild) return base;
|
|
852
|
+
return `${base}_${parse(lastChild)}`;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// Regular subscript
|
|
856
|
+
return `${base}_{${parse(sub)}}`;
|
|
857
|
+
};
|
|
835
858
|
break;
|
|
836
859
|
case 'msup':
|
|
837
860
|
render = getRender_default("@1^{@2}");
|
|
@@ -893,10 +916,32 @@ function getRender(node) {
|
|
|
893
916
|
|
|
894
917
|
function renderTable(node, children) {
|
|
895
918
|
const template = "\\begin{array}{l}@content\\end{array}";
|
|
896
|
-
|
|
919
|
+
// Remove extra backslash and add proper spacing
|
|
920
|
+
const render = getRender_joinSeparator(template, " \\\\ ");
|
|
897
921
|
return render(node, children);
|
|
898
922
|
}
|
|
899
923
|
|
|
924
|
+
function renderMover(node, children) {
|
|
925
|
+
// Check if children exists and has enough elements
|
|
926
|
+
if (!children || children.length < 2) return '';
|
|
927
|
+
|
|
928
|
+
const baseNode = children[0];
|
|
929
|
+
const overNode = children[1];
|
|
930
|
+
|
|
931
|
+
// Check if nodes exist before accessing
|
|
932
|
+
if (!baseNode || !overNode) return '';
|
|
933
|
+
|
|
934
|
+
const overText = NodeTool.getNodeText(overNode)?.trim() || '';
|
|
935
|
+
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
936
|
+
|
|
937
|
+
// Handle vector notation
|
|
938
|
+
if (overText === "→" && isAccent) {
|
|
939
|
+
return `\\vec{${parse(baseNode)}}`;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
return parse(baseNode);
|
|
943
|
+
}
|
|
944
|
+
|
|
900
945
|
function renderMfenced(node, children) {
|
|
901
946
|
const [open, close, separatorsStr] = [
|
|
902
947
|
NodeTool.getAttr(node, 'open', '('),
|
|
@@ -907,9 +952,10 @@ function renderMfenced(node, children) {
|
|
|
907
952
|
const parts = renderChildren(children);
|
|
908
953
|
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
909
954
|
|
|
910
|
-
// Handle
|
|
911
|
-
if (open === ''
|
|
912
|
-
|
|
955
|
+
// Handle system of equations with curly brace
|
|
956
|
+
if (open === '{') {
|
|
957
|
+
// If no closing brace specified, use \right.
|
|
958
|
+
return `\\left\\{${content}${close ? '\\right\\}' : '\\right.'}`;
|
|
913
959
|
}
|
|
914
960
|
|
|
915
961
|
// Handle absolute value notation
|
|
@@ -917,12 +963,7 @@ function renderMfenced(node, children) {
|
|
|
917
963
|
return `\\left|${content}\\right|`;
|
|
918
964
|
}
|
|
919
965
|
|
|
920
|
-
// Regular
|
|
921
|
-
if (open === '(' && close === ')') {
|
|
922
|
-
return `\\left(${content}\\right)`;
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
// Default case
|
|
966
|
+
// Regular cases with proper closing
|
|
926
967
|
return `\\left${open}${content}\\right${close || '.'}`;
|
|
927
968
|
}
|
|
928
969
|
|
|
@@ -1001,62 +1042,6 @@ function renderMmultiscripts(node, children) {
|
|
|
1001
1042
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
1002
1043
|
}
|
|
1003
1044
|
|
|
1004
|
-
function renderMover(node, children) {
|
|
1005
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
1006
|
-
let result = undefined;
|
|
1007
|
-
|
|
1008
|
-
// Get the base node and check if it's a subscript or mrow
|
|
1009
|
-
const baseNode = children[0];
|
|
1010
|
-
const overNode = children[1];
|
|
1011
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1012
|
-
const isSubscript = nodeName === 'msub';
|
|
1013
|
-
const isMrow = nodeName === 'mrow';
|
|
1014
|
-
|
|
1015
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1016
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1017
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1018
|
-
return "\\rightarrow";
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
if (isSubscript) {
|
|
1022
|
-
// Handle case like n₂ with arrow
|
|
1023
|
-
const base = parse(baseNode);
|
|
1024
|
-
return `\\overrightarrow{${base}}`;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
if (isMrow) {
|
|
1028
|
-
// Handle case like 0 with arrow
|
|
1029
|
-
const base = parse(baseNode);
|
|
1030
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1031
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1032
|
-
|
|
1033
|
-
if (overText === "→" && isAccent) {
|
|
1034
|
-
return `\\overrightarrow{${base}}`;
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
// Handle case where there is only an arrow with no base
|
|
1039
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1040
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1041
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1045
|
-
if (!result) {
|
|
1046
|
-
result = parse(nodes[i]);
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
const _overNode = nodes[i + 1];
|
|
1050
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1051
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1052
|
-
|
|
1053
|
-
if (overText === "→" && isAccent) {
|
|
1054
|
-
return `\\overrightarrow{${result}}`;
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
return result;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
1045
|
function renderMunder(node, children){
|
|
1061
1046
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1062
1047
|
let result = undefined;
|
|
@@ -151,7 +151,9 @@
|
|
|
151
151
|
return node.children;
|
|
152
152
|
},
|
|
153
153
|
getNodeName: function(node) {
|
|
154
|
-
|
|
154
|
+
if (!node) return '';
|
|
155
|
+
const localName = node.localName || node.nodeName;
|
|
156
|
+
return localName ? localName.toLowerCase() : '';
|
|
155
157
|
},
|
|
156
158
|
getNodeText: function(node) {
|
|
157
159
|
return node.textContent;
|
|
@@ -708,9 +710,9 @@
|
|
|
708
710
|
function parseOperator(node) {
|
|
709
711
|
let it = NodeTool.getNodeText(node).trim();
|
|
710
712
|
|
|
711
|
-
// Special case for arrow (→)
|
|
713
|
+
// Special case for arrow (→) with proper spacing
|
|
712
714
|
if (it === "→") {
|
|
713
|
-
return "\\rightarrow";
|
|
715
|
+
return " \\rightarrow "; // Add spaces around arrow
|
|
714
716
|
}
|
|
715
717
|
|
|
716
718
|
it = MathSymbol.parseOperator(it);
|
|
@@ -837,7 +839,28 @@
|
|
|
837
839
|
const nodeName = NodeTool.getNodeName(node);
|
|
838
840
|
switch(nodeName){
|
|
839
841
|
case 'msub':
|
|
840
|
-
render =
|
|
842
|
+
render = function(node, children) {
|
|
843
|
+
if (!children || children.length < 2) return '';
|
|
844
|
+
|
|
845
|
+
const base = parse(children[0]);
|
|
846
|
+
if (!base) return '';
|
|
847
|
+
|
|
848
|
+
const sub = children[1];
|
|
849
|
+
if (!sub) return base;
|
|
850
|
+
|
|
851
|
+
// Handle nested subscript with empty mrow
|
|
852
|
+
if (NodeTool.getNodeName(sub) === 'msub' &&
|
|
853
|
+
sub.firstChild &&
|
|
854
|
+
NodeTool.getNodeName(sub.firstChild) === 'mrow' &&
|
|
855
|
+
(!NodeTool.getNodeText(sub.firstChild) || NodeTool.getNodeText(sub.firstChild).trim() === '')) {
|
|
856
|
+
const lastChild = sub.lastChild;
|
|
857
|
+
if (!lastChild) return base;
|
|
858
|
+
return `${base}_${parse(lastChild)}`;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// Regular subscript
|
|
862
|
+
return `${base}_{${parse(sub)}}`;
|
|
863
|
+
};
|
|
841
864
|
break;
|
|
842
865
|
case 'msup':
|
|
843
866
|
render = getRender_default("@1^{@2}");
|
|
@@ -899,10 +922,32 @@
|
|
|
899
922
|
|
|
900
923
|
function renderTable(node, children) {
|
|
901
924
|
const template = "\\begin{array}{l}@content\\end{array}";
|
|
902
|
-
|
|
925
|
+
// Remove extra backslash and add proper spacing
|
|
926
|
+
const render = getRender_joinSeparator(template, " \\\\ ");
|
|
903
927
|
return render(node, children);
|
|
904
928
|
}
|
|
905
929
|
|
|
930
|
+
function renderMover(node, children) {
|
|
931
|
+
// Check if children exists and has enough elements
|
|
932
|
+
if (!children || children.length < 2) return '';
|
|
933
|
+
|
|
934
|
+
const baseNode = children[0];
|
|
935
|
+
const overNode = children[1];
|
|
936
|
+
|
|
937
|
+
// Check if nodes exist before accessing
|
|
938
|
+
if (!baseNode || !overNode) return '';
|
|
939
|
+
|
|
940
|
+
const overText = NodeTool.getNodeText(overNode)?.trim() || '';
|
|
941
|
+
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
942
|
+
|
|
943
|
+
// Handle vector notation
|
|
944
|
+
if (overText === "→" && isAccent) {
|
|
945
|
+
return `\\vec{${parse(baseNode)}}`;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
return parse(baseNode);
|
|
949
|
+
}
|
|
950
|
+
|
|
906
951
|
function renderMfenced(node, children) {
|
|
907
952
|
const [open, close, separatorsStr] = [
|
|
908
953
|
NodeTool.getAttr(node, 'open', '('),
|
|
@@ -913,9 +958,10 @@
|
|
|
913
958
|
const parts = renderChildren(children);
|
|
914
959
|
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
915
960
|
|
|
916
|
-
// Handle
|
|
917
|
-
if (open === ''
|
|
918
|
-
|
|
961
|
+
// Handle system of equations with curly brace
|
|
962
|
+
if (open === '{') {
|
|
963
|
+
// If no closing brace specified, use \right.
|
|
964
|
+
return `\\left\\{${content}${close ? '\\right\\}' : '\\right.'}`;
|
|
919
965
|
}
|
|
920
966
|
|
|
921
967
|
// Handle absolute value notation
|
|
@@ -923,12 +969,7 @@
|
|
|
923
969
|
return `\\left|${content}\\right|`;
|
|
924
970
|
}
|
|
925
971
|
|
|
926
|
-
// Regular
|
|
927
|
-
if (open === '(' && close === ')') {
|
|
928
|
-
return `\\left(${content}\\right)`;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
// Default case
|
|
972
|
+
// Regular cases with proper closing
|
|
932
973
|
return `\\left${open}${content}\\right${close || '.'}`;
|
|
933
974
|
}
|
|
934
975
|
|
|
@@ -1007,62 +1048,6 @@
|
|
|
1007
1048
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
1008
1049
|
}
|
|
1009
1050
|
|
|
1010
|
-
function renderMover(node, children) {
|
|
1011
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
1012
|
-
let result = undefined;
|
|
1013
|
-
|
|
1014
|
-
// Get the base node and check if it's a subscript or mrow
|
|
1015
|
-
const baseNode = children[0];
|
|
1016
|
-
const overNode = children[1];
|
|
1017
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1018
|
-
const isSubscript = nodeName === 'msub';
|
|
1019
|
-
const isMrow = nodeName === 'mrow';
|
|
1020
|
-
|
|
1021
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1022
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1023
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1024
|
-
return "\\rightarrow";
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
if (isSubscript) {
|
|
1028
|
-
// Handle case like n₂ with arrow
|
|
1029
|
-
const base = parse(baseNode);
|
|
1030
|
-
return `\\overrightarrow{${base}}`;
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
if (isMrow) {
|
|
1034
|
-
// Handle case like 0 with arrow
|
|
1035
|
-
const base = parse(baseNode);
|
|
1036
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1037
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1038
|
-
|
|
1039
|
-
if (overText === "→" && isAccent) {
|
|
1040
|
-
return `\\overrightarrow{${base}}`;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
// Handle case where there is only an arrow with no base
|
|
1045
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1046
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1047
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1051
|
-
if (!result) {
|
|
1052
|
-
result = parse(nodes[i]);
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
const _overNode = nodes[i + 1];
|
|
1056
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1057
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1058
|
-
|
|
1059
|
-
if (overText === "→" && isAccent) {
|
|
1060
|
-
return `\\overrightarrow{${result}}`;
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
return result;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
1051
|
function renderMunder(node, children){
|
|
1067
1052
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1068
1053
|
let result = undefined;
|
package/lib/mathml2latex.cjs.js
CHANGED
|
@@ -147,7 +147,9 @@ const NodeTool = {
|
|
|
147
147
|
return node.children;
|
|
148
148
|
},
|
|
149
149
|
getNodeName: function(node) {
|
|
150
|
-
|
|
150
|
+
if (!node) return '';
|
|
151
|
+
const localName = node.localName || node.nodeName;
|
|
152
|
+
return localName ? localName.toLowerCase() : '';
|
|
151
153
|
},
|
|
152
154
|
getNodeText: function(node) {
|
|
153
155
|
return node.textContent;
|
|
@@ -704,9 +706,9 @@ function parseLeaf(node) {
|
|
|
704
706
|
function parseOperator(node) {
|
|
705
707
|
let it = NodeTool.getNodeText(node).trim();
|
|
706
708
|
|
|
707
|
-
// Special case for arrow (→)
|
|
709
|
+
// Special case for arrow (→) with proper spacing
|
|
708
710
|
if (it === "→") {
|
|
709
|
-
return "\\rightarrow";
|
|
711
|
+
return " \\rightarrow "; // Add spaces around arrow
|
|
710
712
|
}
|
|
711
713
|
|
|
712
714
|
it = MathSymbol.parseOperator(it);
|
|
@@ -833,7 +835,28 @@ function getRender(node) {
|
|
|
833
835
|
const nodeName = NodeTool.getNodeName(node);
|
|
834
836
|
switch(nodeName){
|
|
835
837
|
case 'msub':
|
|
836
|
-
render =
|
|
838
|
+
render = function(node, children) {
|
|
839
|
+
if (!children || children.length < 2) return '';
|
|
840
|
+
|
|
841
|
+
const base = parse(children[0]);
|
|
842
|
+
if (!base) return '';
|
|
843
|
+
|
|
844
|
+
const sub = children[1];
|
|
845
|
+
if (!sub) return base;
|
|
846
|
+
|
|
847
|
+
// Handle nested subscript with empty mrow
|
|
848
|
+
if (NodeTool.getNodeName(sub) === 'msub' &&
|
|
849
|
+
sub.firstChild &&
|
|
850
|
+
NodeTool.getNodeName(sub.firstChild) === 'mrow' &&
|
|
851
|
+
(!NodeTool.getNodeText(sub.firstChild) || NodeTool.getNodeText(sub.firstChild).trim() === '')) {
|
|
852
|
+
const lastChild = sub.lastChild;
|
|
853
|
+
if (!lastChild) return base;
|
|
854
|
+
return `${base}_${parse(lastChild)}`;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// Regular subscript
|
|
858
|
+
return `${base}_{${parse(sub)}}`;
|
|
859
|
+
};
|
|
837
860
|
break;
|
|
838
861
|
case 'msup':
|
|
839
862
|
render = getRender_default("@1^{@2}");
|
|
@@ -895,10 +918,32 @@ function getRender(node) {
|
|
|
895
918
|
|
|
896
919
|
function renderTable(node, children) {
|
|
897
920
|
const template = "\\begin{array}{l}@content\\end{array}";
|
|
898
|
-
|
|
921
|
+
// Remove extra backslash and add proper spacing
|
|
922
|
+
const render = getRender_joinSeparator(template, " \\\\ ");
|
|
899
923
|
return render(node, children);
|
|
900
924
|
}
|
|
901
925
|
|
|
926
|
+
function renderMover(node, children) {
|
|
927
|
+
// Check if children exists and has enough elements
|
|
928
|
+
if (!children || children.length < 2) return '';
|
|
929
|
+
|
|
930
|
+
const baseNode = children[0];
|
|
931
|
+
const overNode = children[1];
|
|
932
|
+
|
|
933
|
+
// Check if nodes exist before accessing
|
|
934
|
+
if (!baseNode || !overNode) return '';
|
|
935
|
+
|
|
936
|
+
const overText = NodeTool.getNodeText(overNode)?.trim() || '';
|
|
937
|
+
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
938
|
+
|
|
939
|
+
// Handle vector notation
|
|
940
|
+
if (overText === "→" && isAccent) {
|
|
941
|
+
return `\\vec{${parse(baseNode)}}`;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
return parse(baseNode);
|
|
945
|
+
}
|
|
946
|
+
|
|
902
947
|
function renderMfenced(node, children) {
|
|
903
948
|
const [open, close, separatorsStr] = [
|
|
904
949
|
NodeTool.getAttr(node, 'open', '('),
|
|
@@ -909,9 +954,10 @@ function renderMfenced(node, children) {
|
|
|
909
954
|
const parts = renderChildren(children);
|
|
910
955
|
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
911
956
|
|
|
912
|
-
// Handle
|
|
913
|
-
if (open === ''
|
|
914
|
-
|
|
957
|
+
// Handle system of equations with curly brace
|
|
958
|
+
if (open === '{') {
|
|
959
|
+
// If no closing brace specified, use \right.
|
|
960
|
+
return `\\left\\{${content}${close ? '\\right\\}' : '\\right.'}`;
|
|
915
961
|
}
|
|
916
962
|
|
|
917
963
|
// Handle absolute value notation
|
|
@@ -919,12 +965,7 @@ function renderMfenced(node, children) {
|
|
|
919
965
|
return `\\left|${content}\\right|`;
|
|
920
966
|
}
|
|
921
967
|
|
|
922
|
-
// Regular
|
|
923
|
-
if (open === '(' && close === ')') {
|
|
924
|
-
return `\\left(${content}\\right)`;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
// Default case
|
|
968
|
+
// Regular cases with proper closing
|
|
928
969
|
return `\\left${open}${content}\\right${close || '.'}`;
|
|
929
970
|
}
|
|
930
971
|
|
|
@@ -1003,62 +1044,6 @@ function renderMmultiscripts(node, children) {
|
|
|
1003
1044
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
1004
1045
|
}
|
|
1005
1046
|
|
|
1006
|
-
function renderMover(node, children) {
|
|
1007
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
1008
|
-
let result = undefined;
|
|
1009
|
-
|
|
1010
|
-
// Get the base node and check if it's a subscript or mrow
|
|
1011
|
-
const baseNode = children[0];
|
|
1012
|
-
const overNode = children[1];
|
|
1013
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1014
|
-
const isSubscript = nodeName === 'msub';
|
|
1015
|
-
const isMrow = nodeName === 'mrow';
|
|
1016
|
-
|
|
1017
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1018
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1019
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1020
|
-
return "\\rightarrow";
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
if (isSubscript) {
|
|
1024
|
-
// Handle case like n₂ with arrow
|
|
1025
|
-
const base = parse(baseNode);
|
|
1026
|
-
return `\\overrightarrow{${base}}`;
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
if (isMrow) {
|
|
1030
|
-
// Handle case like 0 with arrow
|
|
1031
|
-
const base = parse(baseNode);
|
|
1032
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1033
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1034
|
-
|
|
1035
|
-
if (overText === "→" && isAccent) {
|
|
1036
|
-
return `\\overrightarrow{${base}}`;
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
// Handle case where there is only an arrow with no base
|
|
1041
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1042
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1043
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1047
|
-
if (!result) {
|
|
1048
|
-
result = parse(nodes[i]);
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
const _overNode = nodes[i + 1];
|
|
1052
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1053
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1054
|
-
|
|
1055
|
-
if (overText === "→" && isAccent) {
|
|
1056
|
-
return `\\overrightarrow{${result}}`;
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
return result;
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
1047
|
function renderMunder(node, children){
|
|
1063
1048
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1064
1049
|
let result = undefined;
|
package/lib/mathml2latex.es.js
CHANGED
|
@@ -145,7 +145,9 @@ const NodeTool = {
|
|
|
145
145
|
return node.children;
|
|
146
146
|
},
|
|
147
147
|
getNodeName: function(node) {
|
|
148
|
-
|
|
148
|
+
if (!node) return '';
|
|
149
|
+
const localName = node.localName || node.nodeName;
|
|
150
|
+
return localName ? localName.toLowerCase() : '';
|
|
149
151
|
},
|
|
150
152
|
getNodeText: function(node) {
|
|
151
153
|
return node.textContent;
|
|
@@ -702,9 +704,9 @@ function parseLeaf(node) {
|
|
|
702
704
|
function parseOperator(node) {
|
|
703
705
|
let it = NodeTool.getNodeText(node).trim();
|
|
704
706
|
|
|
705
|
-
// Special case for arrow (→)
|
|
707
|
+
// Special case for arrow (→) with proper spacing
|
|
706
708
|
if (it === "→") {
|
|
707
|
-
return "\\rightarrow";
|
|
709
|
+
return " \\rightarrow "; // Add spaces around arrow
|
|
708
710
|
}
|
|
709
711
|
|
|
710
712
|
it = MathSymbol.parseOperator(it);
|
|
@@ -831,7 +833,28 @@ function getRender(node) {
|
|
|
831
833
|
const nodeName = NodeTool.getNodeName(node);
|
|
832
834
|
switch(nodeName){
|
|
833
835
|
case 'msub':
|
|
834
|
-
render =
|
|
836
|
+
render = function(node, children) {
|
|
837
|
+
if (!children || children.length < 2) return '';
|
|
838
|
+
|
|
839
|
+
const base = parse(children[0]);
|
|
840
|
+
if (!base) return '';
|
|
841
|
+
|
|
842
|
+
const sub = children[1];
|
|
843
|
+
if (!sub) return base;
|
|
844
|
+
|
|
845
|
+
// Handle nested subscript with empty mrow
|
|
846
|
+
if (NodeTool.getNodeName(sub) === 'msub' &&
|
|
847
|
+
sub.firstChild &&
|
|
848
|
+
NodeTool.getNodeName(sub.firstChild) === 'mrow' &&
|
|
849
|
+
(!NodeTool.getNodeText(sub.firstChild) || NodeTool.getNodeText(sub.firstChild).trim() === '')) {
|
|
850
|
+
const lastChild = sub.lastChild;
|
|
851
|
+
if (!lastChild) return base;
|
|
852
|
+
return `${base}_${parse(lastChild)}`;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// Regular subscript
|
|
856
|
+
return `${base}_{${parse(sub)}}`;
|
|
857
|
+
};
|
|
835
858
|
break;
|
|
836
859
|
case 'msup':
|
|
837
860
|
render = getRender_default("@1^{@2}");
|
|
@@ -893,10 +916,32 @@ function getRender(node) {
|
|
|
893
916
|
|
|
894
917
|
function renderTable(node, children) {
|
|
895
918
|
const template = "\\begin{array}{l}@content\\end{array}";
|
|
896
|
-
|
|
919
|
+
// Remove extra backslash and add proper spacing
|
|
920
|
+
const render = getRender_joinSeparator(template, " \\\\ ");
|
|
897
921
|
return render(node, children);
|
|
898
922
|
}
|
|
899
923
|
|
|
924
|
+
function renderMover(node, children) {
|
|
925
|
+
// Check if children exists and has enough elements
|
|
926
|
+
if (!children || children.length < 2) return '';
|
|
927
|
+
|
|
928
|
+
const baseNode = children[0];
|
|
929
|
+
const overNode = children[1];
|
|
930
|
+
|
|
931
|
+
// Check if nodes exist before accessing
|
|
932
|
+
if (!baseNode || !overNode) return '';
|
|
933
|
+
|
|
934
|
+
const overText = NodeTool.getNodeText(overNode)?.trim() || '';
|
|
935
|
+
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
936
|
+
|
|
937
|
+
// Handle vector notation
|
|
938
|
+
if (overText === "→" && isAccent) {
|
|
939
|
+
return `\\vec{${parse(baseNode)}}`;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
return parse(baseNode);
|
|
943
|
+
}
|
|
944
|
+
|
|
900
945
|
function renderMfenced(node, children) {
|
|
901
946
|
const [open, close, separatorsStr] = [
|
|
902
947
|
NodeTool.getAttr(node, 'open', '('),
|
|
@@ -907,9 +952,10 @@ function renderMfenced(node, children) {
|
|
|
907
952
|
const parts = renderChildren(children);
|
|
908
953
|
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
909
954
|
|
|
910
|
-
// Handle
|
|
911
|
-
if (open === ''
|
|
912
|
-
|
|
955
|
+
// Handle system of equations with curly brace
|
|
956
|
+
if (open === '{') {
|
|
957
|
+
// If no closing brace specified, use \right.
|
|
958
|
+
return `\\left\\{${content}${close ? '\\right\\}' : '\\right.'}`;
|
|
913
959
|
}
|
|
914
960
|
|
|
915
961
|
// Handle absolute value notation
|
|
@@ -917,12 +963,7 @@ function renderMfenced(node, children) {
|
|
|
917
963
|
return `\\left|${content}\\right|`;
|
|
918
964
|
}
|
|
919
965
|
|
|
920
|
-
// Regular
|
|
921
|
-
if (open === '(' && close === ')') {
|
|
922
|
-
return `\\left(${content}\\right)`;
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
// Default case
|
|
966
|
+
// Regular cases with proper closing
|
|
926
967
|
return `\\left${open}${content}\\right${close || '.'}`;
|
|
927
968
|
}
|
|
928
969
|
|
|
@@ -1001,62 +1042,6 @@ function renderMmultiscripts(node, children) {
|
|
|
1001
1042
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
1002
1043
|
}
|
|
1003
1044
|
|
|
1004
|
-
function renderMover(node, children) {
|
|
1005
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
1006
|
-
let result = undefined;
|
|
1007
|
-
|
|
1008
|
-
// Get the base node and check if it's a subscript or mrow
|
|
1009
|
-
const baseNode = children[0];
|
|
1010
|
-
const overNode = children[1];
|
|
1011
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1012
|
-
const isSubscript = nodeName === 'msub';
|
|
1013
|
-
const isMrow = nodeName === 'mrow';
|
|
1014
|
-
|
|
1015
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1016
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1017
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1018
|
-
return "\\rightarrow";
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
if (isSubscript) {
|
|
1022
|
-
// Handle case like n₂ with arrow
|
|
1023
|
-
const base = parse(baseNode);
|
|
1024
|
-
return `\\overrightarrow{${base}}`;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
if (isMrow) {
|
|
1028
|
-
// Handle case like 0 with arrow
|
|
1029
|
-
const base = parse(baseNode);
|
|
1030
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1031
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1032
|
-
|
|
1033
|
-
if (overText === "→" && isAccent) {
|
|
1034
|
-
return `\\overrightarrow{${base}}`;
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
// Handle case where there is only an arrow with no base
|
|
1039
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1040
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1041
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1045
|
-
if (!result) {
|
|
1046
|
-
result = parse(nodes[i]);
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
const _overNode = nodes[i + 1];
|
|
1050
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1051
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1052
|
-
|
|
1053
|
-
if (overText === "→" && isAccent) {
|
|
1054
|
-
return `\\overrightarrow{${result}}`;
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
return result;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
1045
|
function renderMunder(node, children){
|
|
1061
1046
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1062
1047
|
let result = undefined;
|
package/lib/mathml2latex.umd.js
CHANGED
|
@@ -151,7 +151,9 @@
|
|
|
151
151
|
return node.children;
|
|
152
152
|
},
|
|
153
153
|
getNodeName: function(node) {
|
|
154
|
-
|
|
154
|
+
if (!node) return '';
|
|
155
|
+
const localName = node.localName || node.nodeName;
|
|
156
|
+
return localName ? localName.toLowerCase() : '';
|
|
155
157
|
},
|
|
156
158
|
getNodeText: function(node) {
|
|
157
159
|
return node.textContent;
|
|
@@ -708,9 +710,9 @@
|
|
|
708
710
|
function parseOperator(node) {
|
|
709
711
|
let it = NodeTool.getNodeText(node).trim();
|
|
710
712
|
|
|
711
|
-
// Special case for arrow (→)
|
|
713
|
+
// Special case for arrow (→) with proper spacing
|
|
712
714
|
if (it === "→") {
|
|
713
|
-
return "\\rightarrow";
|
|
715
|
+
return " \\rightarrow "; // Add spaces around arrow
|
|
714
716
|
}
|
|
715
717
|
|
|
716
718
|
it = MathSymbol.parseOperator(it);
|
|
@@ -837,7 +839,28 @@
|
|
|
837
839
|
const nodeName = NodeTool.getNodeName(node);
|
|
838
840
|
switch(nodeName){
|
|
839
841
|
case 'msub':
|
|
840
|
-
render =
|
|
842
|
+
render = function(node, children) {
|
|
843
|
+
if (!children || children.length < 2) return '';
|
|
844
|
+
|
|
845
|
+
const base = parse(children[0]);
|
|
846
|
+
if (!base) return '';
|
|
847
|
+
|
|
848
|
+
const sub = children[1];
|
|
849
|
+
if (!sub) return base;
|
|
850
|
+
|
|
851
|
+
// Handle nested subscript with empty mrow
|
|
852
|
+
if (NodeTool.getNodeName(sub) === 'msub' &&
|
|
853
|
+
sub.firstChild &&
|
|
854
|
+
NodeTool.getNodeName(sub.firstChild) === 'mrow' &&
|
|
855
|
+
(!NodeTool.getNodeText(sub.firstChild) || NodeTool.getNodeText(sub.firstChild).trim() === '')) {
|
|
856
|
+
const lastChild = sub.lastChild;
|
|
857
|
+
if (!lastChild) return base;
|
|
858
|
+
return `${base}_${parse(lastChild)}`;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// Regular subscript
|
|
862
|
+
return `${base}_{${parse(sub)}}`;
|
|
863
|
+
};
|
|
841
864
|
break;
|
|
842
865
|
case 'msup':
|
|
843
866
|
render = getRender_default("@1^{@2}");
|
|
@@ -899,10 +922,32 @@
|
|
|
899
922
|
|
|
900
923
|
function renderTable(node, children) {
|
|
901
924
|
const template = "\\begin{array}{l}@content\\end{array}";
|
|
902
|
-
|
|
925
|
+
// Remove extra backslash and add proper spacing
|
|
926
|
+
const render = getRender_joinSeparator(template, " \\\\ ");
|
|
903
927
|
return render(node, children);
|
|
904
928
|
}
|
|
905
929
|
|
|
930
|
+
function renderMover(node, children) {
|
|
931
|
+
// Check if children exists and has enough elements
|
|
932
|
+
if (!children || children.length < 2) return '';
|
|
933
|
+
|
|
934
|
+
const baseNode = children[0];
|
|
935
|
+
const overNode = children[1];
|
|
936
|
+
|
|
937
|
+
// Check if nodes exist before accessing
|
|
938
|
+
if (!baseNode || !overNode) return '';
|
|
939
|
+
|
|
940
|
+
const overText = NodeTool.getNodeText(overNode)?.trim() || '';
|
|
941
|
+
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
942
|
+
|
|
943
|
+
// Handle vector notation
|
|
944
|
+
if (overText === "→" && isAccent) {
|
|
945
|
+
return `\\vec{${parse(baseNode)}}`;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
return parse(baseNode);
|
|
949
|
+
}
|
|
950
|
+
|
|
906
951
|
function renderMfenced(node, children) {
|
|
907
952
|
const [open, close, separatorsStr] = [
|
|
908
953
|
NodeTool.getAttr(node, 'open', '('),
|
|
@@ -913,9 +958,10 @@
|
|
|
913
958
|
const parts = renderChildren(children);
|
|
914
959
|
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
915
960
|
|
|
916
|
-
// Handle
|
|
917
|
-
if (open === ''
|
|
918
|
-
|
|
961
|
+
// Handle system of equations with curly brace
|
|
962
|
+
if (open === '{') {
|
|
963
|
+
// If no closing brace specified, use \right.
|
|
964
|
+
return `\\left\\{${content}${close ? '\\right\\}' : '\\right.'}`;
|
|
919
965
|
}
|
|
920
966
|
|
|
921
967
|
// Handle absolute value notation
|
|
@@ -923,12 +969,7 @@
|
|
|
923
969
|
return `\\left|${content}\\right|`;
|
|
924
970
|
}
|
|
925
971
|
|
|
926
|
-
// Regular
|
|
927
|
-
if (open === '(' && close === ')') {
|
|
928
|
-
return `\\left(${content}\\right)`;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
// Default case
|
|
972
|
+
// Regular cases with proper closing
|
|
932
973
|
return `\\left${open}${content}\\right${close || '.'}`;
|
|
933
974
|
}
|
|
934
975
|
|
|
@@ -1007,62 +1048,6 @@
|
|
|
1007
1048
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
1008
1049
|
}
|
|
1009
1050
|
|
|
1010
|
-
function renderMover(node, children) {
|
|
1011
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
1012
|
-
let result = undefined;
|
|
1013
|
-
|
|
1014
|
-
// Get the base node and check if it's a subscript or mrow
|
|
1015
|
-
const baseNode = children[0];
|
|
1016
|
-
const overNode = children[1];
|
|
1017
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1018
|
-
const isSubscript = nodeName === 'msub';
|
|
1019
|
-
const isMrow = nodeName === 'mrow';
|
|
1020
|
-
|
|
1021
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1022
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1023
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1024
|
-
return "\\rightarrow";
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
if (isSubscript) {
|
|
1028
|
-
// Handle case like n₂ with arrow
|
|
1029
|
-
const base = parse(baseNode);
|
|
1030
|
-
return `\\overrightarrow{${base}}`;
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
if (isMrow) {
|
|
1034
|
-
// Handle case like 0 with arrow
|
|
1035
|
-
const base = parse(baseNode);
|
|
1036
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1037
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1038
|
-
|
|
1039
|
-
if (overText === "→" && isAccent) {
|
|
1040
|
-
return `\\overrightarrow{${base}}`;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
// Handle case where there is only an arrow with no base
|
|
1045
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1046
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1047
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1051
|
-
if (!result) {
|
|
1052
|
-
result = parse(nodes[i]);
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
const _overNode = nodes[i + 1];
|
|
1056
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1057
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1058
|
-
|
|
1059
|
-
if (overText === "→" && isAccent) {
|
|
1060
|
-
return `\\overrightarrow{${result}}`;
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
return result;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
1051
|
function renderMunder(node, children){
|
|
1067
1052
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1068
1053
|
let result = undefined;
|