ed-mathml2tex 0.0.7 → 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 +67 -70
- package/lib/mathml2latex.browser.es.js +67 -70
- package/lib/mathml2latex.browser.umd.js +67 -70
- package/lib/mathml2latex.cjs.js +67 -70
- package/lib/mathml2latex.es.js +67 -70
- package/lib/mathml2latex.umd.js +67 -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,25 +918,55 @@ 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
|
-
NodeTool.getAttr(node, 'open', '
|
|
905
|
-
NodeTool.getAttr(node, 'close', '
|
|
906
|
-
NodeTool.getAttr(node, 'separators', '
|
|
949
|
+
NodeTool.getAttr(node, 'open', '('),
|
|
950
|
+
NodeTool.getAttr(node, 'close', ')'),
|
|
951
|
+
NodeTool.getAttr(node, 'separators', ',')
|
|
907
952
|
];
|
|
908
953
|
|
|
909
954
|
const parts = renderChildren(children);
|
|
910
|
-
const content = parts.join(separatorsStr).trim();
|
|
955
|
+
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
911
956
|
|
|
912
|
-
|
|
913
|
-
|
|
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.'}`;
|
|
914
961
|
}
|
|
915
962
|
|
|
916
|
-
|
|
963
|
+
// Handle absolute value notation
|
|
964
|
+
if (open === '|' && (close === '|' || close === '')) {
|
|
965
|
+
return `\\left|${content}\\right|`;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// Regular cases with proper closing
|
|
969
|
+
return `\\left${open}${content}\\right${close || '.'}`;
|
|
917
970
|
}
|
|
918
971
|
|
|
919
972
|
function renderMfrac(node, children){
|
|
@@ -933,9 +986,9 @@ function renderMfrac(node, children){
|
|
|
933
986
|
if((prevNode && NodeTool.getNodeText(prevNode).trim() === '(') &&
|
|
934
987
|
(nextNode && NodeTool.getNodeText(nextNode).trim() === ')')
|
|
935
988
|
) {
|
|
936
|
-
render = getRender_default("\\
|
|
989
|
+
render = getRender_default("\\binom{@1}{@2}");
|
|
937
990
|
} else {
|
|
938
|
-
render = getRender_default("{}
|
|
991
|
+
render = getRender_default("\\frac{@1}{@2}");
|
|
939
992
|
}
|
|
940
993
|
} else {
|
|
941
994
|
render = getRender_default("\\frac{@1}{@2}");
|
|
@@ -991,62 +1044,6 @@ function renderMmultiscripts(node, children) {
|
|
|
991
1044
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
992
1045
|
}
|
|
993
1046
|
|
|
994
|
-
function renderMover(node, children) {
|
|
995
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
996
|
-
let result = undefined;
|
|
997
|
-
|
|
998
|
-
// Get the base node and check if it's a subscript or mrow
|
|
999
|
-
const baseNode = children[0];
|
|
1000
|
-
const overNode = children[1];
|
|
1001
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1002
|
-
const isSubscript = nodeName === 'msub';
|
|
1003
|
-
const isMrow = nodeName === 'mrow';
|
|
1004
|
-
|
|
1005
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1006
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1007
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1008
|
-
return "\\rightarrow";
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
if (isSubscript) {
|
|
1012
|
-
// Handle case like n₂ with arrow
|
|
1013
|
-
const base = parse(baseNode);
|
|
1014
|
-
return `\\overrightarrow{${base}}`;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
if (isMrow) {
|
|
1018
|
-
// Handle case like 0 with arrow
|
|
1019
|
-
const base = parse(baseNode);
|
|
1020
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1021
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1022
|
-
|
|
1023
|
-
if (overText === "→" && isAccent) {
|
|
1024
|
-
return `\\overrightarrow{${base}}`;
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
// Handle case where there is only an arrow with no base
|
|
1029
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1030
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1031
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1035
|
-
if (!result) {
|
|
1036
|
-
result = parse(nodes[i]);
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
const _overNode = nodes[i + 1];
|
|
1040
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1041
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1042
|
-
|
|
1043
|
-
if (overText === "→" && isAccent) {
|
|
1044
|
-
return `\\overrightarrow{${result}}`;
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
return result;
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
1047
|
function renderMunder(node, children){
|
|
1051
1048
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1052
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,25 +916,55 @@ 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
|
-
NodeTool.getAttr(node, 'open', '
|
|
903
|
-
NodeTool.getAttr(node, 'close', '
|
|
904
|
-
NodeTool.getAttr(node, 'separators', '
|
|
947
|
+
NodeTool.getAttr(node, 'open', '('),
|
|
948
|
+
NodeTool.getAttr(node, 'close', ')'),
|
|
949
|
+
NodeTool.getAttr(node, 'separators', ',')
|
|
905
950
|
];
|
|
906
951
|
|
|
907
952
|
const parts = renderChildren(children);
|
|
908
|
-
const content = parts.join(separatorsStr).trim();
|
|
953
|
+
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
909
954
|
|
|
910
|
-
|
|
911
|
-
|
|
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.'}`;
|
|
912
959
|
}
|
|
913
960
|
|
|
914
|
-
|
|
961
|
+
// Handle absolute value notation
|
|
962
|
+
if (open === '|' && (close === '|' || close === '')) {
|
|
963
|
+
return `\\left|${content}\\right|`;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// Regular cases with proper closing
|
|
967
|
+
return `\\left${open}${content}\\right${close || '.'}`;
|
|
915
968
|
}
|
|
916
969
|
|
|
917
970
|
function renderMfrac(node, children){
|
|
@@ -931,9 +984,9 @@ function renderMfrac(node, children){
|
|
|
931
984
|
if((prevNode && NodeTool.getNodeText(prevNode).trim() === '(') &&
|
|
932
985
|
(nextNode && NodeTool.getNodeText(nextNode).trim() === ')')
|
|
933
986
|
) {
|
|
934
|
-
render = getRender_default("\\
|
|
987
|
+
render = getRender_default("\\binom{@1}{@2}");
|
|
935
988
|
} else {
|
|
936
|
-
render = getRender_default("{}
|
|
989
|
+
render = getRender_default("\\frac{@1}{@2}");
|
|
937
990
|
}
|
|
938
991
|
} else {
|
|
939
992
|
render = getRender_default("\\frac{@1}{@2}");
|
|
@@ -989,62 +1042,6 @@ function renderMmultiscripts(node, children) {
|
|
|
989
1042
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
990
1043
|
}
|
|
991
1044
|
|
|
992
|
-
function renderMover(node, children) {
|
|
993
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
994
|
-
let result = undefined;
|
|
995
|
-
|
|
996
|
-
// Get the base node and check if it's a subscript or mrow
|
|
997
|
-
const baseNode = children[0];
|
|
998
|
-
const overNode = children[1];
|
|
999
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1000
|
-
const isSubscript = nodeName === 'msub';
|
|
1001
|
-
const isMrow = nodeName === 'mrow';
|
|
1002
|
-
|
|
1003
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1004
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1005
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1006
|
-
return "\\rightarrow";
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
if (isSubscript) {
|
|
1010
|
-
// Handle case like n₂ with arrow
|
|
1011
|
-
const base = parse(baseNode);
|
|
1012
|
-
return `\\overrightarrow{${base}}`;
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
if (isMrow) {
|
|
1016
|
-
// Handle case like 0 with arrow
|
|
1017
|
-
const base = parse(baseNode);
|
|
1018
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1019
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1020
|
-
|
|
1021
|
-
if (overText === "→" && isAccent) {
|
|
1022
|
-
return `\\overrightarrow{${base}}`;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
// Handle case where there is only an arrow with no base
|
|
1027
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1028
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1029
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1033
|
-
if (!result) {
|
|
1034
|
-
result = parse(nodes[i]);
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
const _overNode = nodes[i + 1];
|
|
1038
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1039
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1040
|
-
|
|
1041
|
-
if (overText === "→" && isAccent) {
|
|
1042
|
-
return `\\overrightarrow{${result}}`;
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
return result;
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
1045
|
function renderMunder(node, children){
|
|
1049
1046
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1050
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,25 +922,55 @@
|
|
|
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
|
-
NodeTool.getAttr(node, 'open', '
|
|
909
|
-
NodeTool.getAttr(node, 'close', '
|
|
910
|
-
NodeTool.getAttr(node, 'separators', '
|
|
953
|
+
NodeTool.getAttr(node, 'open', '('),
|
|
954
|
+
NodeTool.getAttr(node, 'close', ')'),
|
|
955
|
+
NodeTool.getAttr(node, 'separators', ',')
|
|
911
956
|
];
|
|
912
957
|
|
|
913
958
|
const parts = renderChildren(children);
|
|
914
|
-
const content = parts.join(separatorsStr).trim();
|
|
959
|
+
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
915
960
|
|
|
916
|
-
|
|
917
|
-
|
|
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.'}`;
|
|
918
965
|
}
|
|
919
966
|
|
|
920
|
-
|
|
967
|
+
// Handle absolute value notation
|
|
968
|
+
if (open === '|' && (close === '|' || close === '')) {
|
|
969
|
+
return `\\left|${content}\\right|`;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// Regular cases with proper closing
|
|
973
|
+
return `\\left${open}${content}\\right${close || '.'}`;
|
|
921
974
|
}
|
|
922
975
|
|
|
923
976
|
function renderMfrac(node, children){
|
|
@@ -937,9 +990,9 @@
|
|
|
937
990
|
if((prevNode && NodeTool.getNodeText(prevNode).trim() === '(') &&
|
|
938
991
|
(nextNode && NodeTool.getNodeText(nextNode).trim() === ')')
|
|
939
992
|
) {
|
|
940
|
-
render = getRender_default("\\
|
|
993
|
+
render = getRender_default("\\binom{@1}{@2}");
|
|
941
994
|
} else {
|
|
942
|
-
render = getRender_default("{}
|
|
995
|
+
render = getRender_default("\\frac{@1}{@2}");
|
|
943
996
|
}
|
|
944
997
|
} else {
|
|
945
998
|
render = getRender_default("\\frac{@1}{@2}");
|
|
@@ -995,62 +1048,6 @@
|
|
|
995
1048
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
996
1049
|
}
|
|
997
1050
|
|
|
998
|
-
function renderMover(node, children) {
|
|
999
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
1000
|
-
let result = undefined;
|
|
1001
|
-
|
|
1002
|
-
// Get the base node and check if it's a subscript or mrow
|
|
1003
|
-
const baseNode = children[0];
|
|
1004
|
-
const overNode = children[1];
|
|
1005
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1006
|
-
const isSubscript = nodeName === 'msub';
|
|
1007
|
-
const isMrow = nodeName === 'mrow';
|
|
1008
|
-
|
|
1009
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1010
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1011
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1012
|
-
return "\\rightarrow";
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
if (isSubscript) {
|
|
1016
|
-
// Handle case like n₂ with arrow
|
|
1017
|
-
const base = parse(baseNode);
|
|
1018
|
-
return `\\overrightarrow{${base}}`;
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
if (isMrow) {
|
|
1022
|
-
// Handle case like 0 with arrow
|
|
1023
|
-
const base = parse(baseNode);
|
|
1024
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1025
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1026
|
-
|
|
1027
|
-
if (overText === "→" && isAccent) {
|
|
1028
|
-
return `\\overrightarrow{${base}}`;
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
// Handle case where there is only an arrow with no base
|
|
1033
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1034
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1035
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1039
|
-
if (!result) {
|
|
1040
|
-
result = parse(nodes[i]);
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
const _overNode = nodes[i + 1];
|
|
1044
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1045
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1046
|
-
|
|
1047
|
-
if (overText === "→" && isAccent) {
|
|
1048
|
-
return `\\overrightarrow{${result}}`;
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
return result;
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
1051
|
function renderMunder(node, children){
|
|
1055
1052
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1056
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,25 +918,55 @@ 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
|
-
NodeTool.getAttr(node, 'open', '
|
|
905
|
-
NodeTool.getAttr(node, 'close', '
|
|
906
|
-
NodeTool.getAttr(node, 'separators', '
|
|
949
|
+
NodeTool.getAttr(node, 'open', '('),
|
|
950
|
+
NodeTool.getAttr(node, 'close', ')'),
|
|
951
|
+
NodeTool.getAttr(node, 'separators', ',')
|
|
907
952
|
];
|
|
908
953
|
|
|
909
954
|
const parts = renderChildren(children);
|
|
910
|
-
const content = parts.join(separatorsStr).trim();
|
|
955
|
+
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
911
956
|
|
|
912
|
-
|
|
913
|
-
|
|
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.'}`;
|
|
914
961
|
}
|
|
915
962
|
|
|
916
|
-
|
|
963
|
+
// Handle absolute value notation
|
|
964
|
+
if (open === '|' && (close === '|' || close === '')) {
|
|
965
|
+
return `\\left|${content}\\right|`;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// Regular cases with proper closing
|
|
969
|
+
return `\\left${open}${content}\\right${close || '.'}`;
|
|
917
970
|
}
|
|
918
971
|
|
|
919
972
|
function renderMfrac(node, children){
|
|
@@ -933,9 +986,9 @@ function renderMfrac(node, children){
|
|
|
933
986
|
if((prevNode && NodeTool.getNodeText(prevNode).trim() === '(') &&
|
|
934
987
|
(nextNode && NodeTool.getNodeText(nextNode).trim() === ')')
|
|
935
988
|
) {
|
|
936
|
-
render = getRender_default("\\
|
|
989
|
+
render = getRender_default("\\binom{@1}{@2}");
|
|
937
990
|
} else {
|
|
938
|
-
render = getRender_default("{}
|
|
991
|
+
render = getRender_default("\\frac{@1}{@2}");
|
|
939
992
|
}
|
|
940
993
|
} else {
|
|
941
994
|
render = getRender_default("\\frac{@1}{@2}");
|
|
@@ -991,62 +1044,6 @@ function renderMmultiscripts(node, children) {
|
|
|
991
1044
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
992
1045
|
}
|
|
993
1046
|
|
|
994
|
-
function renderMover(node, children) {
|
|
995
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
996
|
-
let result = undefined;
|
|
997
|
-
|
|
998
|
-
// Get the base node and check if it's a subscript or mrow
|
|
999
|
-
const baseNode = children[0];
|
|
1000
|
-
const overNode = children[1];
|
|
1001
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1002
|
-
const isSubscript = nodeName === 'msub';
|
|
1003
|
-
const isMrow = nodeName === 'mrow';
|
|
1004
|
-
|
|
1005
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1006
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1007
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1008
|
-
return "\\rightarrow";
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
if (isSubscript) {
|
|
1012
|
-
// Handle case like n₂ with arrow
|
|
1013
|
-
const base = parse(baseNode);
|
|
1014
|
-
return `\\overrightarrow{${base}}`;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
if (isMrow) {
|
|
1018
|
-
// Handle case like 0 with arrow
|
|
1019
|
-
const base = parse(baseNode);
|
|
1020
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1021
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1022
|
-
|
|
1023
|
-
if (overText === "→" && isAccent) {
|
|
1024
|
-
return `\\overrightarrow{${base}}`;
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
// Handle case where there is only an arrow with no base
|
|
1029
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1030
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1031
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1035
|
-
if (!result) {
|
|
1036
|
-
result = parse(nodes[i]);
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
const _overNode = nodes[i + 1];
|
|
1040
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1041
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1042
|
-
|
|
1043
|
-
if (overText === "→" && isAccent) {
|
|
1044
|
-
return `\\overrightarrow{${result}}`;
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
return result;
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
1047
|
function renderMunder(node, children){
|
|
1051
1048
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1052
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,25 +916,55 @@ 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
|
-
NodeTool.getAttr(node, 'open', '
|
|
903
|
-
NodeTool.getAttr(node, 'close', '
|
|
904
|
-
NodeTool.getAttr(node, 'separators', '
|
|
947
|
+
NodeTool.getAttr(node, 'open', '('),
|
|
948
|
+
NodeTool.getAttr(node, 'close', ')'),
|
|
949
|
+
NodeTool.getAttr(node, 'separators', ',')
|
|
905
950
|
];
|
|
906
951
|
|
|
907
952
|
const parts = renderChildren(children);
|
|
908
|
-
const content = parts.join(separatorsStr).trim();
|
|
953
|
+
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
909
954
|
|
|
910
|
-
|
|
911
|
-
|
|
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.'}`;
|
|
912
959
|
}
|
|
913
960
|
|
|
914
|
-
|
|
961
|
+
// Handle absolute value notation
|
|
962
|
+
if (open === '|' && (close === '|' || close === '')) {
|
|
963
|
+
return `\\left|${content}\\right|`;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// Regular cases with proper closing
|
|
967
|
+
return `\\left${open}${content}\\right${close || '.'}`;
|
|
915
968
|
}
|
|
916
969
|
|
|
917
970
|
function renderMfrac(node, children){
|
|
@@ -931,9 +984,9 @@ function renderMfrac(node, children){
|
|
|
931
984
|
if((prevNode && NodeTool.getNodeText(prevNode).trim() === '(') &&
|
|
932
985
|
(nextNode && NodeTool.getNodeText(nextNode).trim() === ')')
|
|
933
986
|
) {
|
|
934
|
-
render = getRender_default("\\
|
|
987
|
+
render = getRender_default("\\binom{@1}{@2}");
|
|
935
988
|
} else {
|
|
936
|
-
render = getRender_default("{}
|
|
989
|
+
render = getRender_default("\\frac{@1}{@2}");
|
|
937
990
|
}
|
|
938
991
|
} else {
|
|
939
992
|
render = getRender_default("\\frac{@1}{@2}");
|
|
@@ -989,62 +1042,6 @@ function renderMmultiscripts(node, children) {
|
|
|
989
1042
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
990
1043
|
}
|
|
991
1044
|
|
|
992
|
-
function renderMover(node, children) {
|
|
993
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
994
|
-
let result = undefined;
|
|
995
|
-
|
|
996
|
-
// Get the base node and check if it's a subscript or mrow
|
|
997
|
-
const baseNode = children[0];
|
|
998
|
-
const overNode = children[1];
|
|
999
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1000
|
-
const isSubscript = nodeName === 'msub';
|
|
1001
|
-
const isMrow = nodeName === 'mrow';
|
|
1002
|
-
|
|
1003
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1004
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1005
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1006
|
-
return "\\rightarrow";
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
if (isSubscript) {
|
|
1010
|
-
// Handle case like n₂ with arrow
|
|
1011
|
-
const base = parse(baseNode);
|
|
1012
|
-
return `\\overrightarrow{${base}}`;
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
if (isMrow) {
|
|
1016
|
-
// Handle case like 0 with arrow
|
|
1017
|
-
const base = parse(baseNode);
|
|
1018
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1019
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1020
|
-
|
|
1021
|
-
if (overText === "→" && isAccent) {
|
|
1022
|
-
return `\\overrightarrow{${base}}`;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
// Handle case where there is only an arrow with no base
|
|
1027
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1028
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1029
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1033
|
-
if (!result) {
|
|
1034
|
-
result = parse(nodes[i]);
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
const _overNode = nodes[i + 1];
|
|
1038
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1039
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1040
|
-
|
|
1041
|
-
if (overText === "→" && isAccent) {
|
|
1042
|
-
return `\\overrightarrow{${result}}`;
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
return result;
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
1045
|
function renderMunder(node, children){
|
|
1049
1046
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1050
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,25 +922,55 @@
|
|
|
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
|
-
NodeTool.getAttr(node, 'open', '
|
|
909
|
-
NodeTool.getAttr(node, 'close', '
|
|
910
|
-
NodeTool.getAttr(node, 'separators', '
|
|
953
|
+
NodeTool.getAttr(node, 'open', '('),
|
|
954
|
+
NodeTool.getAttr(node, 'close', ')'),
|
|
955
|
+
NodeTool.getAttr(node, 'separators', ',')
|
|
911
956
|
];
|
|
912
957
|
|
|
913
958
|
const parts = renderChildren(children);
|
|
914
|
-
const content = parts.join(separatorsStr).trim();
|
|
959
|
+
const content = parts.join(separatorsStr === '|' ? ',' : separatorsStr).trim();
|
|
915
960
|
|
|
916
|
-
|
|
917
|
-
|
|
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.'}`;
|
|
918
965
|
}
|
|
919
966
|
|
|
920
|
-
|
|
967
|
+
// Handle absolute value notation
|
|
968
|
+
if (open === '|' && (close === '|' || close === '')) {
|
|
969
|
+
return `\\left|${content}\\right|`;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// Regular cases with proper closing
|
|
973
|
+
return `\\left${open}${content}\\right${close || '.'}`;
|
|
921
974
|
}
|
|
922
975
|
|
|
923
976
|
function renderMfrac(node, children){
|
|
@@ -937,9 +990,9 @@
|
|
|
937
990
|
if((prevNode && NodeTool.getNodeText(prevNode).trim() === '(') &&
|
|
938
991
|
(nextNode && NodeTool.getNodeText(nextNode).trim() === ')')
|
|
939
992
|
) {
|
|
940
|
-
render = getRender_default("\\
|
|
993
|
+
render = getRender_default("\\binom{@1}{@2}");
|
|
941
994
|
} else {
|
|
942
|
-
render = getRender_default("{}
|
|
995
|
+
render = getRender_default("\\frac{@1}{@2}");
|
|
943
996
|
}
|
|
944
997
|
} else {
|
|
945
998
|
render = getRender_default("\\frac{@1}{@2}");
|
|
@@ -995,62 +1048,6 @@
|
|
|
995
1048
|
return [renderScripts(prevScripts), base, renderScripts(backScripts)].join('');
|
|
996
1049
|
}
|
|
997
1050
|
|
|
998
|
-
function renderMover(node, children) {
|
|
999
|
-
const nodes = flattenNodeTreeByNodeName(node, 'mover');
|
|
1000
|
-
let result = undefined;
|
|
1001
|
-
|
|
1002
|
-
// Get the base node and check if it's a subscript or mrow
|
|
1003
|
-
const baseNode = children[0];
|
|
1004
|
-
const overNode = children[1];
|
|
1005
|
-
const nodeName = NodeTool.getNodeName(baseNode);
|
|
1006
|
-
const isSubscript = nodeName === 'msub';
|
|
1007
|
-
const isMrow = nodeName === 'mrow';
|
|
1008
|
-
|
|
1009
|
-
// Handle case where the base is an arrow and mrow is above
|
|
1010
|
-
const baseText = NodeTool.getNodeText(baseNode).trim();
|
|
1011
|
-
if (baseText === "→" && NodeTool.getNodeName(overNode) === "mrow") {
|
|
1012
|
-
return "\\rightarrow";
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
if (isSubscript) {
|
|
1016
|
-
// Handle case like n₂ with arrow
|
|
1017
|
-
const base = parse(baseNode);
|
|
1018
|
-
return `\\overrightarrow{${base}}`;
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
if (isMrow) {
|
|
1022
|
-
// Handle case like 0 with arrow
|
|
1023
|
-
const base = parse(baseNode);
|
|
1024
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1025
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1026
|
-
|
|
1027
|
-
if (overText === "→" && isAccent) {
|
|
1028
|
-
return `\\overrightarrow{${base}}`;
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
// Handle case where there is only an arrow with no base
|
|
1033
|
-
const overText = NodeTool.getNodeText(overNode).trim();
|
|
1034
|
-
if (overText === "→" && NodeTool.getNodeText(baseNode).trim() === "") {
|
|
1035
|
-
return `\\rightarrow`; // Return just the arrow
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
for (let i = 0; i < nodes.length - 1; i++) {
|
|
1039
|
-
if (!result) {
|
|
1040
|
-
result = parse(nodes[i]);
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
const _overNode = nodes[i + 1];
|
|
1044
|
-
const overText = NodeTool.getNodeText(_overNode).trim();
|
|
1045
|
-
const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
|
|
1046
|
-
|
|
1047
|
-
if (overText === "→" && isAccent) {
|
|
1048
|
-
return `\\overrightarrow{${result}}`;
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
return result;
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
1051
|
function renderMunder(node, children){
|
|
1055
1052
|
const nodes = flattenNodeTreeByNodeName(node, 'munder');
|
|
1056
1053
|
let result = undefined;
|