ed-mathml2tex 0.1.5 → 0.1.7

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.
@@ -582,10 +582,10 @@ T.createMarker = function() {
582
582
  }
583
583
  };
584
584
 
585
- function getRender_joinSeparator(template, separator = '') {
585
+ function getRender_joinSeparator(template, separator = "") {
586
586
  return function (node, children) {
587
587
  const parts = renderChildren(children);
588
- return template.replace('@content', parts.join(separator));
588
+ return template.replace("@content", parts.join(separator));
589
589
  };
590
590
  }
591
591
 
@@ -597,9 +597,11 @@ function convert(mathmlHtml) {
597
597
  result = result.replace(/\\right\.\./g, "\\right."); // Loại bỏ dấu chấm trùng lặp
598
598
  result = result.replace(/\.\s*\./g, "."); // Loại bỏ dấu chấm trùng lặp
599
599
 
600
- if (mathmlHtml.includes("<munder>") &&
600
+ if (
601
+ mathmlHtml.includes("<munder>") &&
601
602
  mathmlHtml.includes("<mo>→</mo>") &&
602
- mathmlHtml.includes("<mrow/>")) {
603
+ mathmlHtml.includes("<mrow/>")
604
+ ) {
603
605
  if (result.includes("\\limits")) {
604
606
  result = "\\underset{}{\\rightarrow}";
605
607
  }
@@ -608,38 +610,71 @@ function convert(mathmlHtml) {
608
610
  // Thêm xử lý cho các thẻ MathML khác
609
611
  result = result
610
612
  .replace(/∞/g, "\\infty") // Vô cực
611
- .replace(/∑/g, "\\sum") // Tổng
612
- .replace(/∏/g, "\\prod") // Tích
613
- .replace(/∫/g, "\\int"); // Tích phân
613
+ .replace(/∑/g, "\\sum") // Tổng
614
+ .replace(/∏/g, "\\prod") // Tích
615
+ .replace(/∫/g, "\\int"); // Tích phân
614
616
 
615
617
  return result;
616
618
  }
617
619
 
618
620
  function toLatex(result) {
619
621
  // Xử lý binomial coefficients
620
- result = result.replace(/\\left\(\\DELETE_BRACKET_L/g, '');
621
- result = result.replace(/\\DELETE_BRACKET_R\\right\)/g, '');
622
- result = result.replace(/\\DELETE_BRACKET_L/g, '');
623
- result = result.replace(/\\DELETE_BRACKET_R/g, '');
622
+ result = result.replace(/\\left\(\\DELETE_BRACKET_L/g, "");
623
+ result = result.replace(/\\DELETE_BRACKET_R\\right\)/g, "");
624
+ result = result.replace(/\\DELETE_BRACKET_L/g, "");
625
+ result = result.replace(/\\DELETE_BRACKET_R/g, "");
624
626
 
625
627
  // Xử lý các trường hợp mũi tên với giới hạn
626
628
  result = result.replace(/→\\limits_{}/g, "\\underset{}{\\rightarrow}");
627
629
  result = result.replace(/→\\limits_{(\s*)}/g, "\\underset{}{\\rightarrow}");
628
- result = result.replace(/\\rightarrow\\limits_{}/g, "\\underset{}{\\rightarrow}");
629
- result = result.replace(/\\rightarrow\\limits_{(\s*)}/g, "\\underset{}{\\rightarrow}");
630
-
631
- result = result.replace(/→\\limits_\{([^}]*)\}/g, "\\underset{$1}{\\rightarrow}");
632
- result = result.replace(/\\rightarrow\\limits_\{([^}]*)\}/g, "\\underset{$1}{\\rightarrow}");
633
-
634
- result = result.replace(/→\\limits_\{([^}]*)\}\^\{([^}]*)\}/g, "\\overset{$2}{\\underset{$1}{\\rightarrow}}");
635
- result = result.replace(/\\rightarrow\\limits_\{([^}]*)\}\^\{([^}]*)\}/g, "\\overset{$2}{\\underset{$1}{\\rightarrow}}");
630
+ result = result.replace(
631
+ /\\rightarrow\\limits_{}/g,
632
+ "\\underset{}{\\rightarrow}"
633
+ );
634
+ result = result.replace(
635
+ /\\rightarrow\\limits_{(\s*)}/g,
636
+ "\\underset{}{\\rightarrow}"
637
+ );
638
+
639
+ result = result.replace(
640
+ /→\\limits_\{([^}]*)\}/g,
641
+ "\\underset{$1}{\\rightarrow}"
642
+ );
643
+ result = result.replace(
644
+ /\\rightarrow\\limits_\{([^}]*)\}/g,
645
+ "\\underset{$1}{\\rightarrow}"
646
+ );
647
+
648
+ result = result.replace(
649
+ /→\\limits_\{([^}]*)\}\^\{([^}]*)\}/g,
650
+ "\\overset{$2}{\\underset{$1}{\\rightarrow}}"
651
+ );
652
+ result = result.replace(
653
+ /\\rightarrow\\limits_\{([^}]*)\}\^\{([^}]*)\}/g,
654
+ "\\overset{$2}{\\underset{$1}{\\rightarrow}}"
655
+ );
636
656
 
637
657
  // Xử lý vector và các ký hiệu đặc biệt
638
- result = result.replace(/([^{}\s]+)\^\{\\rightarrow\}/g, "\\overrightarrow{$1}");
639
- result = result.replace(/\{([^{}]+)\}\^\{\\rightarrow\}/g, "\\overrightarrow{$1}");
640
- result = result.replace(/([A-Za-z0-9]+)_\{([^{}]+)\}\^\{\\rightarrow\}/g, "\\overrightarrow{$1_{$2}}");
641
- result = result.replace(/([A-Za-z0-9]+)_([0-9])\^\{\\rightarrow\}/g, "\\overrightarrow{$1_$2}");
642
- result = result.replace(/(\([^()]+\))\^\{\\rightarrow\}/g, "\\overrightarrow{$1}");
658
+ result = result.replace(
659
+ /([^{}\s]+)\^\{\\rightarrow\}/g,
660
+ "\\overrightarrow{$1}"
661
+ );
662
+ result = result.replace(
663
+ /\{([^{}]+)\}\^\{\\rightarrow\}/g,
664
+ "\\overrightarrow{$1}"
665
+ );
666
+ result = result.replace(
667
+ /([A-Za-z0-9]+)_\{([^{}]+)\}\^\{\\rightarrow\}/g,
668
+ "\\overrightarrow{$1_{$2}}"
669
+ );
670
+ result = result.replace(
671
+ /([A-Za-z0-9]+)_([0-9])\^\{\\rightarrow\}/g,
672
+ "\\overrightarrow{$1_$2}"
673
+ );
674
+ result = result.replace(
675
+ /(\([^()]+\))\^\{\\rightarrow\}/g,
676
+ "\\overrightarrow{$1}"
677
+ );
643
678
 
644
679
  // Remove or comment out these lines in toLatex function
645
680
  // Thêm xử lý các ký hiệu toán học phổ biến
@@ -667,7 +702,7 @@ function parse(node) {
667
702
  // @see https://www.w3.org/TR/MathML3/chapter7.html
668
703
  // Cải tiến parseLeaf để hỗ trợ thêm các ký hiệu
669
704
  function parseLeaf(node) {
670
- let r = '';
705
+ let r = "";
671
706
  const nodeName = NodeTool.getNodeName(node);
672
707
 
673
708
  if (nodeName === "mrow" && NodeTool.getNodeText(node).trim() === "") {
@@ -675,32 +710,32 @@ function parseLeaf(node) {
675
710
  }
676
711
 
677
712
  switch (nodeName) {
678
- case 'mi':
713
+ case "mi":
679
714
  r = parseElementMi(node);
680
715
  break;
681
- case 'mn':
716
+ case "mn":
682
717
  r = parseElementMn(node);
683
718
  break;
684
- case 'mo':
719
+ case "mo":
685
720
  r = parseOperator(node);
686
721
  break;
687
- case 'ms':
722
+ case "ms":
688
723
  r = parseElementMs(node);
689
724
  break;
690
- case 'mtext':
725
+ case "mtext":
691
726
  r = parseElementMtext(node);
692
727
  break;
693
- case 'mglyph':
728
+ case "mglyph":
694
729
  r = parseElementMglyph(node);
695
730
  break;
696
- case 'mprescripts':
697
- r = '';
731
+ case "mprescripts":
732
+ r = "";
698
733
  break;
699
- case 'mspace':
734
+ case "mspace":
700
735
  r = parseElementMspace();
701
736
  break;
702
- case 'none':
703
- r = '\\:';
737
+ case "none":
738
+ r = "\\:";
704
739
  break;
705
740
  default:
706
741
  r = escapeSpecialChars(NodeTool.getNodeText(node).trim());
@@ -709,10 +744,10 @@ function parseLeaf(node) {
709
744
  return r;
710
745
  }
711
746
 
712
- // Cải tiến parseOperator để hỗ trợ thêm toán tử
747
+ // --- PATCH by AI: Fix for set-builder notation and fraction output ---
748
+ // 1. Extend operatorMap and add π->\pi, |->\mid
713
749
  function parseOperator(node) {
714
750
  let it = NodeTool.getNodeText(node).trim();
715
-
716
751
  const operatorMap = {
717
752
  "→": " \\rightarrow ",
718
753
  "←": " \\leftarrow ",
@@ -731,12 +766,14 @@ function parseOperator(node) {
731
766
  ">": " > ",
732
767
  "=": " = ",
733
768
  ",": ", ", // Dấu phẩy trong tập hợp
734
- ";": ";", // Dấu chấm phẩy không cần khoảng trắng
735
- "Ω": "\\Omega" // Thêm ký hiệu Omega
769
+ ";": ";",
770
+ Ω: "\\Omega",
771
+ "|": " \\mid ", // PATCH: set-builder mid
772
+ π: " \\pi ", // PATCH: Greek letter
736
773
  };
737
-
738
774
  return operatorMap[it] || escapeSpecialChars(MathSymbol.parseOperator(it));
739
775
  }
776
+ // --- END PATCH ---
740
777
 
741
778
  // Math identifier
742
779
  function parseElementMi(node) {
@@ -744,7 +781,7 @@ function parseElementMi(node) {
744
781
 
745
782
  // Handle vectors (e.g. AB', AI)
746
783
  if (it.includes("'")) {
747
- return it; // Return as is to handle in mrow
784
+ return it; // Return as is to handle in mrow
748
785
  }
749
786
 
750
787
  // Handle subscripts (e.g. n₂)
@@ -768,27 +805,41 @@ function parseElementMn(node) {
768
805
  function parseElementMs(node) {
769
806
  const content = NodeTool.getNodeText(node).trimRight();
770
807
  const it = escapeSpecialChars(content);
771
- return ['"', it, '"'].join('');
808
+ return ['"', it, '"'].join("");
772
809
  }
773
810
 
774
811
  // Math Text
775
812
  function parseElementMtext(node) {
776
813
  let content = NodeTool.getNodeText(node)
777
814
  // Handle operators and spacing only
778
- .replace(/\s*=\s*/g, ' = ')
779
- .replace(/\s*\.\s*/g, ' \\cdot ')
815
+ .replace(/\s*=\s*/g, " = ")
816
+ .replace(/\s*\.\s*/g, " \\cdot ")
780
817
  .trim();
781
818
 
819
+ const specialMTextMap = {
820
+ ℝ: "\\mathbb{R}",
821
+ ℤ: "\\mathbb{Z}",
822
+ ℕ: "\\mathbb{N}",
823
+ ℚ: "\\mathbb{Q}",
824
+ ℂ: "\\mathbb{C}",
825
+ "\\": "\\setminus ",
826
+ "|": "\\mid ",
827
+ " ": "",
828
+ };
829
+ if (specialMTextMap[content]) return specialMTextMap[content];
830
+
782
831
  // Handle units with proper \mathrm formatting
783
- if (content.includes('(') && content.includes(')')) {
832
+ if (content.includes("(") && content.includes(")")) {
784
833
  const parts = content.split(/(\([^)]+\))/);
785
- content = parts.map(part => {
786
- if (part.startsWith('(') && part.endsWith(')')) {
787
- // Keep original characters in units
788
- return `\\mathrm{${part}}`;
789
- }
790
- return part;
791
- }).join('');
834
+ content = parts
835
+ .map((part) => {
836
+ if (part.startsWith("(") && part.endsWith(")")) {
837
+ // Keep original characters in units
838
+ return `\\mathrm{${part}}`;
839
+ }
840
+ return part;
841
+ })
842
+ .join("");
792
843
  }
793
844
 
794
845
  return content;
@@ -796,84 +847,124 @@ function parseElementMtext(node) {
796
847
 
797
848
  // Math glyph (image)
798
849
  function parseElementMglyph(node) {
799
- const it = ['"', NodeTool.getAttr(node, 'alt', ''), '"'].join('');
850
+ const it = ['"', NodeTool.getAttr(node, "alt", ""), '"'].join("");
800
851
  return escapeSpecialChars(it);
801
852
  }
802
853
 
803
854
  // TODO need or not
804
855
  function parseElementMspace(node) {
805
- return '';
856
+ return "";
806
857
  }
807
858
 
808
859
  function escapeSpecialChars(text) {
860
+ // Don't escape pi, Greek, or just a-z0-9 or Unicode Greek, or empty
861
+ if (
862
+ /^\\?[a-zA-Z0-9]+$/.test(text) ||
863
+ /^\\(?:pi|alpha|beta|gamma|Omega)$/.test(text) ||
864
+ /^π$/.test(text) ||
865
+ !text
866
+ ) {
867
+ return text;
868
+ }
869
+ // Otherwise escape only true reserved LaTeX
809
870
  const specialChars = /\$|%|_|&|#|\{|\}/g;
810
- text = text.replace(specialChars, char => `\\${char}`);
871
+ text = text.replace(specialChars, (char) => `\\${char}`);
811
872
  return text;
812
873
  }
813
874
 
814
-
815
875
  function parseContainer(node, children) {
816
876
  const render = getRender(node);
817
877
  if (render) {
818
878
  return render(node, children);
819
879
  } else {
820
- throw new Error(`Couldn't get render function for container node: ${NodeTool.getNodeName(node)}`);
880
+ throw new Error(
881
+ `Couldn't get render function for container node: ${NodeTool.getNodeName(
882
+ node
883
+ )}`
884
+ );
821
885
  }
822
886
  }
823
887
 
824
888
  function renderChildren(children) {
825
889
  const parts = [];
826
890
  let lefts = [];
827
- Array.prototype.forEach.call(children, (node) => {
828
- if (NodeTool.getNodeName(node) === 'mo') {
891
+
892
+ // PATCH: Special case for set-builder style: leading { ... trailing }
893
+ if (
894
+ children.length >= 3 &&
895
+ NodeTool.getNodeName(children[0]) === "mo" &&
896
+ NodeTool.getNodeText(children[0]).trim() === "{" &&
897
+ NodeTool.getNodeName(children[children.length - 1]) === "mo" &&
898
+ NodeTool.getNodeText(children[children.length - 1]).trim() === "}"
899
+ ) {
900
+ // Render inner content
901
+ const innerContent = Array.prototype.slice
902
+ .call(children, 1, -1)
903
+ .map((child) => parse(child))
904
+ .join("");
905
+ return `\\left\\{${innerContent}\\right\\}`;
906
+ }
907
+
908
+ Array.prototype.forEach.call(children, (node, idx) => {
909
+ // PATCH: Thin space between variables/numbers in mfrac numerator (k 2 π)
910
+ if (
911
+ NodeTool.getNodeName(node) === "mrow" &&
912
+ node.parentNode &&
913
+ NodeTool.getNodeName(node.parentNode) === "mfrac"
914
+ ) {
915
+ const mrowKids = Array.from(NodeTool.getChildren(node));
916
+ if (
917
+ mrowKids.every((n) =>
918
+ ["mi", "mn", "mo"].includes(NodeTool.getNodeName(n))
919
+ )
920
+ ) {
921
+ // Only vars, nums, ops (possibly Greek); join with thin space
922
+ const str = mrowKids.map((k) => parse(k)).join("\\,");
923
+ parts.push(str);
924
+ return;
925
+ }
926
+ }
927
+ // END PATCH
928
+ if (NodeTool.getNodeName(node) === "mo") {
829
929
  const op = NodeTool.getNodeText(node).trim();
830
930
  if (Brackets.contains(op)) {
831
- let stretchy = NodeTool.getAttr(node, 'stretchy', 'true');
832
- stretchy = ['', 'true'].indexOf(stretchy) > -1;
931
+ let stretchy = NodeTool.getAttr(node, "stretchy", "true");
932
+ stretchy = ["", "true"].indexOf(stretchy) > -1;
933
+
934
+ // Luôn escape dấu ngoặc nhọn cho LaTeX
935
+ let escapedOp = op;
936
+ if (op === "{" || op === "}") {
937
+ escapedOp = `\\${op}`;
938
+ }
833
939
 
834
940
  if (Brackets.isRight(op)) {
835
941
  const nearLeft = lefts[lefts.length - 1];
836
- if (nearLeft) {
837
- if (Brackets.isPair(nearLeft, op)) {
838
- // Kiểm tra xem có phải là một phần của biểu thức mũ không
839
- const parentNode = node.parentNode;
840
- const nextSibling = node.nextSibling;
841
- const prevSibling = node.previousSibling;
842
-
843
- const isInPower = parentNode && (
844
- NodeTool.getNodeName(parentNode) === 'msup' ||
845
- (nextSibling && NodeTool.getNodeName(nextSibling) === 'msup') ||
846
- (prevSibling && NodeTool.getNodeName(prevSibling) === 'msup')
847
- );
848
-
849
- if (isInPower) {
850
- parts.push(op); // Không thêm \right cho ngoặc trong mũ
851
- } else {
852
- parts.push(op); // Chỉ thêm dấu ngoặc đơn giản
853
- }
854
- lefts.pop();
942
+ if (nearLeft && Brackets.isPair(nearLeft, op)) {
943
+ const parentNode = node.parentNode;
944
+ const isInPower =
945
+ parentNode && NodeTool.getNodeName(parentNode) === "msup";
946
+
947
+ if (stretchy && !isInPower) {
948
+ parts.push(`\\right${escapedOp}`); // Dùng escapedOp
855
949
  } else {
856
- parts.push(op);
950
+ parts.push(escapedOp); // Dùng escapedOp
857
951
  }
952
+ lefts.pop();
858
953
  } else {
859
- parts.push(op);
954
+ parts.push(escapedOp); // Ngoặc phải không khớp
860
955
  }
861
956
  } else {
862
- // Kiểm tra cho dấu ngoặc mở
957
+ // ngoặc trái
863
958
  const parentNode = node.parentNode;
864
- const nextSibling = node.nextSibling;
865
-
866
- const isInPower = parentNode && (
867
- NodeTool.getNodeName(parentNode) === 'msup' ||
868
- (nextSibling && NodeTool.getNodeName(nextSibling) === 'msup')
869
- );
870
-
871
- if (isInPower) {
872
- parts.push(op); // Không thêm \left cho ngoặc trong mũ
959
+ const isInPower =
960
+ parentNode && NodeTool.getNodeName(parentNode) === "msup";
961
+
962
+ if (stretchy && !isInPower) {
963
+ parts.push(`\\left${escapedOp}`); // Dùng escapedOp
873
964
  } else {
874
- parts.push(op); // Chỉ thêm dấu ngoặc đơn giản
965
+ parts.push(escapedOp); // Dùng escapedOp
875
966
  }
876
- lefts.push(op);
967
+ lefts.push(op); // Dùng `op` gốc để so sánh cặp
877
968
  }
878
969
  } else {
879
970
  parts.push(parseOperator(node));
@@ -882,7 +973,6 @@ function renderChildren(children) {
882
973
  parts.push(parse(node));
883
974
  }
884
975
  });
885
-
886
976
  lefts = undefined;
887
977
  return parts;
888
978
  }
@@ -892,41 +982,49 @@ function getRender(node) {
892
982
  const nodeName = NodeTool.getNodeName(node);
893
983
 
894
984
  switch (nodeName) {
895
- case 'mrow':
985
+ case "mrow":
896
986
  render = function (node, children) {
897
987
  const childrenArray = Array.from(children);
898
- if (childrenArray.length >= 2 &&
899
- NodeTool.getNodeName(childrenArray[0]) === 'mo' &&
900
- NodeTool.getNodeName(childrenArray[childrenArray.length - 1]) === 'mo') {
988
+ if (
989
+ childrenArray.length >= 2 &&
990
+ NodeTool.getNodeName(childrenArray[0]) === "mo" &&
991
+ NodeTool.getNodeName(childrenArray[childrenArray.length - 1]) === "mo"
992
+ ) {
901
993
  const firstOp = NodeTool.getNodeText(childrenArray[0]).trim();
902
- const lastOp = NodeTool.getNodeText(childrenArray[childrenArray.length - 1]).trim();
994
+ const lastOp = NodeTool.getNodeText(
995
+ childrenArray[childrenArray.length - 1]
996
+ ).trim();
903
997
 
904
998
  // Xử lý đặc biệt cho dấu ngoặc nhọn chứa mtable
905
- if (firstOp === '{' && childrenArray.some(child =>
906
- NodeTool.getNodeName(child) === 'mtable')) {
999
+ if (
1000
+ firstOp === "{" &&
1001
+ childrenArray.some(
1002
+ (child) => NodeTool.getNodeName(child) === "mtable"
1003
+ )
1004
+ ) {
907
1005
  const innerContent = childrenArray
908
1006
  .slice(1, -1)
909
- .map(child => parse(child))
910
- .join('');
1007
+ .map((child) => parse(child))
1008
+ .join("");
911
1009
  return `\\left\\{${innerContent}\\right.`;
912
1010
  }
913
1011
 
914
1012
  // Xử lý cho trường hợp [a;b) và [a,b)
915
- if (firstOp === '[' && lastOp === ')') {
1013
+ if (firstOp === "[" && lastOp === ")") {
916
1014
  const innerContent = childrenArray
917
1015
  .slice(1, -1)
918
- .map(child => parse(child))
919
- .join('');
1016
+ .map((child) => parse(child))
1017
+ .join("");
920
1018
  return `\\left[${innerContent}\\right)`;
921
1019
  }
922
1020
 
923
1021
  // Xử lý ngoặc nhọn bình thường
924
- if (firstOp === '{' && lastOp === '}') {
1022
+ if (firstOp === "{" && lastOp === "}") {
925
1023
  const innerContent = childrenArray
926
1024
  .slice(1, -1)
927
- .map(child => parse(child))
928
- .join('');
929
- return `\\{${innerContent}\\}`;
1025
+ .map((child) => parse(child))
1026
+ .join("");
1027
+ return `\\left\\{${innerContent}\\right\\}`;
930
1028
  }
931
1029
 
932
1030
  // Bỏ qua nếu firstOp là rỗng (trường hợp <mo></mo>)
@@ -934,33 +1032,55 @@ function getRender(node) {
934
1032
  return getRender_joinSeparator("@content")(node, childrenArray);
935
1033
  }
936
1034
 
1035
+ if (firstOp === "[" && lastOp === "]") {
1036
+ const innerContent = childrenArray
1037
+ .slice(1, -1)
1038
+ .map((child) => parse(child))
1039
+ .join("");
1040
+ return `[${innerContent}]`;
1041
+ }
1042
+
937
1043
  // Xử lý đặc biệt cho dấu ngoặc vuông chứa mtable
938
- if (firstOp === '[') {
1044
+ if (firstOp === "[") {
939
1045
  const innerContent = childrenArray
940
1046
  .slice(1, -1) // Bỏ dấu ngoặc mở và đóng
941
- .map(child => {
1047
+ .map((child) => {
942
1048
  const parsed = parse(child);
943
1049
  // Nếu child là mtable, trả về nội dung đã được định dạng với \begin{array}{l} ... \end{array}
944
- if (NodeTool.getNodeName(child) === 'mtable') {
945
- const rows = Array.from(NodeTool.getChildren(child)).map(row => {
946
- const rowChildren = Array.from(NodeTool.getChildren(row));
947
- return rowChildren.map(cell => parse(cell)).join('');
948
- });
949
- return `\\begin{array}{l} ${rows.join(' \\\\ ')} \\end{array}`;
1050
+ if (NodeTool.getNodeName(child) === "mtable") {
1051
+ const rows = Array.from(NodeTool.getChildren(child)).map(
1052
+ (row) => {
1053
+ const rowChildren = Array.from(NodeTool.getChildren(row));
1054
+ return rowChildren.map((cell) => parse(cell)).join("");
1055
+ }
1056
+ );
1057
+ return `\\begin{array}{l} ${rows.join(
1058
+ " \\\\ "
1059
+ )} \\end{array}`;
950
1060
  }
951
1061
  // Nếu child là mrow chứa mtable, xử lý tương tự
952
- if (NodeTool.getNodeName(child) === 'mrow' &&
953
- Array.from(NodeTool.getChildren(child)).some(c => NodeTool.getNodeName(c) === 'mtable')) {
954
- const mtableChild = Array.from(NodeTool.getChildren(child)).find(c => NodeTool.getNodeName(c) === 'mtable');
955
- const rows = Array.from(NodeTool.getChildren(mtableChild)).map(row => {
1062
+ if (
1063
+ NodeTool.getNodeName(child) === "mrow" &&
1064
+ Array.from(NodeTool.getChildren(child)).some(
1065
+ (c) => NodeTool.getNodeName(c) === "mtable"
1066
+ )
1067
+ ) {
1068
+ const mtableChild = Array.from(
1069
+ NodeTool.getChildren(child)
1070
+ ).find((c) => NodeTool.getNodeName(c) === "mtable");
1071
+ const rows = Array.from(
1072
+ NodeTool.getChildren(mtableChild)
1073
+ ).map((row) => {
956
1074
  const rowChildren = Array.from(NodeTool.getChildren(row));
957
- return rowChildren.map(cell => parse(cell)).join('');
1075
+ return rowChildren.map((cell) => parse(cell)).join("");
958
1076
  });
959
- return `\\begin{array}{l} ${rows.join(' \\\\ ')} \\end{array}`;
1077
+ return `\\begin{array}{l} ${rows.join(
1078
+ " \\\\ "
1079
+ )} \\end{array}`;
960
1080
  }
961
1081
  return parsed;
962
1082
  })
963
- .join('');
1083
+ .join("");
964
1084
 
965
1085
  // Giữ nguyên dấu ngoặc vuông lớn
966
1086
  return `\\left[${innerContent}\\right.`;
@@ -969,36 +1089,41 @@ function getRender(node) {
969
1089
  if (Brackets.isPair(firstOp, lastOp)) {
970
1090
  const innerContent = childrenArray
971
1091
  .slice(1, -1)
972
- .map(child => parse(child))
973
- .join('');
1092
+ .map((child) => parse(child))
1093
+ .join("");
974
1094
  return `\\left${firstOp}${innerContent}\\right${lastOp}`;
975
1095
  }
976
1096
 
977
1097
  // Giữ nguyên dấu ngoặc nhọn trong MathML
978
- if (firstOp === '{' || lastOp === '}') {
1098
+ if (firstOp === "{" || lastOp === "}") {
979
1099
  const innerContent = childrenArray
980
- .slice(1, lastOp === '}' ? -1 : undefined)
981
- .map(child => parse(child))
982
- .join('');
983
- return `${firstOp === '{' ? '\\{' : ''}${innerContent}${lastOp === '}' ? '\\}' : ''}`;
1100
+ .slice(1, lastOp === "}" ? -1 : undefined)
1101
+ .map((child) => parse(child))
1102
+ .join("");
1103
+ return `${firstOp === "{" ? "\\{" : ""}${innerContent}${
1104
+ lastOp === "}" ? "\\}" : ""
1105
+ }`;
984
1106
  }
985
1107
  }
986
1108
  return getRender_joinSeparator("@content")(node, childrenArray);
987
1109
  };
988
1110
  break;
989
1111
 
990
- case 'msub':
1112
+ case "msub":
991
1113
  render = function (node, children) {
992
1114
  const childrenArray = Array.from(children);
993
- if (!childrenArray || childrenArray.length < 2) return '';
994
- const base = parse(childrenArray[0]) || '';
1115
+ if (!childrenArray || childrenArray.length < 2) return "";
1116
+ const base = parse(childrenArray[0]) || "";
995
1117
  const sub = childrenArray[1];
996
1118
  if (!sub) return base;
997
1119
 
998
- if (NodeTool.getNodeName(sub) === 'msub' &&
1120
+ if (
1121
+ NodeTool.getNodeName(sub) === "msub" &&
999
1122
  sub.firstChild &&
1000
- NodeTool.getNodeName(sub.firstChild) === 'mrow' &&
1001
- (!NodeTool.getNodeText(sub.firstChild) || NodeTool.getNodeText(sub.firstChild).trim() === '')) {
1123
+ NodeTool.getNodeName(sub.firstChild) === "mrow" &&
1124
+ (!NodeTool.getNodeText(sub.firstChild) ||
1125
+ NodeTool.getNodeText(sub.firstChild).trim() === "")
1126
+ ) {
1002
1127
  const lastChild = sub.lastChild;
1003
1128
  return lastChild ? `${base}_${parse(lastChild)}` : base;
1004
1129
  }
@@ -1006,52 +1131,57 @@ function getRender(node) {
1006
1131
  };
1007
1132
  break;
1008
1133
 
1009
- case 'msup':
1134
+ case "msup":
1010
1135
  render = function (node, children) {
1011
1136
  const childrenArray = Array.from(children);
1012
- if (!childrenArray || childrenArray.length < 2) return '';
1013
- const base = parse(childrenArray[0]) || '';
1014
- const sup = parse(childrenArray[1]) || '';
1137
+ if (!childrenArray || childrenArray.length < 2) return "";
1138
+ const base = parse(childrenArray[0]) || "";
1139
+ const sup = parse(childrenArray[1]) || "";
1015
1140
  return `${base}^{${sup}}`;
1016
1141
  };
1017
1142
  break;
1018
1143
 
1019
- case 'msubsup':
1144
+ case "msubsup":
1020
1145
  render = function (node, children) {
1021
1146
  const childrenArray = Array.from(children);
1022
- if (!childrenArray || childrenArray.length < 3) return '';
1147
+ if (!childrenArray || childrenArray.length < 3) return "";
1023
1148
  const base = parse(childrenArray[0]);
1024
1149
  const sub = parse(childrenArray[1]);
1025
1150
  const sup = parse(childrenArray[2]);
1026
1151
 
1027
1152
  const lastChild = childrenArray[0].lastElementChild;
1028
- if (lastChild && NodeTool.getNodeName(lastChild) === 'mo' &&
1029
- NodeTool.getNodeText(lastChild).trim() === '|') {
1153
+ if (
1154
+ lastChild &&
1155
+ NodeTool.getNodeName(lastChild) === "mo" &&
1156
+ NodeTool.getNodeText(lastChild).trim() === "|"
1157
+ ) {
1030
1158
  const content = Array.from(childrenArray[0].children)
1031
1159
  .slice(0, -1)
1032
- .map(child => parse(child))
1033
- .join('');
1160
+ .map((child) => parse(child))
1161
+ .join("");
1034
1162
  return `\\left.${content}\\right|_{${sub}}^{${sup}}`;
1035
1163
  }
1036
1164
  return `${base}_{${sub}}^{${sup}}`;
1037
1165
  };
1038
1166
  break;
1039
1167
 
1040
- case 'mover':
1168
+ case "mover":
1041
1169
  render = function (node, children) {
1042
1170
  const childrenArray = Array.from(children);
1043
- if (!childrenArray || childrenArray.length < 2) return '';
1044
- const base = parse(childrenArray[0]) || '';
1045
- const over = parse(childrenArray[1]) || '';
1046
- const overText = NodeTool.getNodeText(childrenArray[1])?.trim() || '';
1171
+ if (!childrenArray || childrenArray.length < 2) return "";
1172
+ const base = parse(childrenArray[0]) || "";
1173
+ const over = parse(childrenArray[1]) || "";
1174
+ const overText = NodeTool.getNodeText(childrenArray[1])?.trim() || "";
1047
1175
  const isAccent = NodeTool.getAttr(node, "accent", "false") === "true";
1048
1176
 
1049
1177
  // Handle biology notation (double overline)
1050
1178
  if (overText === "¯") {
1051
1179
  const parentNode = node.parentNode;
1052
1180
  // Check if this is part of a double overline structure
1053
- if (NodeTool.getNodeName(parentNode) === 'mover' &&
1054
- NodeTool.getNodeText(parentNode.lastChild)?.trim() === '¯') {
1181
+ if (
1182
+ NodeTool.getNodeName(parentNode) === "mover" &&
1183
+ NodeTool.getNodeText(parentNode.lastChild)?.trim() === "¯"
1184
+ ) {
1055
1185
  return `\\overline{${base}}`;
1056
1186
  }
1057
1187
  return `\\overline{${base}}`;
@@ -1063,55 +1193,68 @@ function getRender(node) {
1063
1193
  };
1064
1194
  break;
1065
1195
 
1066
- case 'munder':
1196
+ case "munder":
1067
1197
  render = function (node, children) {
1068
1198
  const childrenArray = Array.from(children);
1069
- if (!childrenArray || childrenArray.length < 2) return '';
1070
- const base = parse(childrenArray[0]) || '';
1071
- const under = parse(childrenArray[1]) || '';
1072
- const isUnderAccent = NodeTool.getAttr(node, "accentunder", "false") === "true";
1199
+ if (!childrenArray || childrenArray.length < 2) return "";
1200
+ const base = parse(childrenArray[0]) || "";
1201
+ const under = parse(childrenArray[1]) || "";
1202
+ const isUnderAccent =
1203
+ NodeTool.getAttr(node, "accentunder", "false") === "true";
1073
1204
 
1074
1205
  if (base === "∫") return `\\int_{${under}}`;
1075
1206
  return `\\underset{${under}}{${base}}`;
1076
1207
  };
1077
1208
  break;
1078
1209
 
1079
- case 'munderover':
1210
+ case "munderover":
1080
1211
  render = function (node, children) {
1081
1212
  const childrenArray = Array.from(children);
1082
- if (!childrenArray || childrenArray.length < 3) return '';
1213
+ if (!childrenArray || childrenArray.length < 3) return "";
1083
1214
  const base = parse(childrenArray[0]);
1084
1215
  const under = parse(childrenArray[1]);
1085
1216
  const over = parse(childrenArray[2]);
1086
1217
  const baseText = NodeTool.getNodeText(childrenArray[0]).trim();
1087
1218
 
1088
- if (baseText === '∫') return `\\int_{${under}}^{${over}}`;
1089
- if (baseText === '∑') return `\\sum_{${under}}^{${over}}`;
1090
- if (baseText === '∏') return `\\prod_{${under}}^{${over}}`;
1091
- if (baseText === '|') return `\\big|_{${under}}^{${over}}`;
1219
+ // Special handling for chemical reaction arrow
1220
+ if (
1221
+ baseText === "→" &&
1222
+ NodeTool.getNodeName(childrenArray[1]) === "msup"
1223
+ ) {
1224
+ return `\\xrightarrow[${under}]{${over}}`;
1225
+ }
1226
+
1227
+ if (baseText === "∫") return `\\int_{${under}}^{${over}}`;
1228
+ if (baseText === "∑") return `\\sum_{${under}}^{${over}}`;
1229
+ if (baseText === "∏") return `\\prod_{${under}}^{${over}}`;
1230
+ if (baseText === "|") return `\\big|_{${under}}^{${over}}`;
1092
1231
  return `${base}_{${under}}^{${over}}`;
1093
1232
  };
1094
1233
  break;
1095
1234
 
1096
- case 'mmultiscripts':
1235
+ case "mmultiscripts":
1097
1236
  render = function (node, children) {
1098
1237
  const childrenArray = Array.from(children);
1099
- if (!childrenArray || childrenArray.length < 1) return '';
1238
+ if (!childrenArray || childrenArray.length < 1) return "";
1100
1239
  const base = parse(childrenArray[0]);
1101
- let prescripts = '';
1102
- let postscripts = '';
1240
+ let prescripts = "";
1241
+ let postscripts = "";
1103
1242
  let i = 1;
1104
1243
 
1105
1244
  while (i < childrenArray.length) {
1106
- if (NodeTool.getNodeName(childrenArray[i]) === 'mprescripts') {
1245
+ if (NodeTool.getNodeName(childrenArray[i]) === "mprescripts") {
1107
1246
  i++;
1108
1247
  if (i + 1 < childrenArray.length) {
1109
- prescripts = `_{${parse(childrenArray[i])}}^{${parse(childrenArray[i + 1])}}`;
1248
+ prescripts = `_{${parse(childrenArray[i])}}^{${parse(
1249
+ childrenArray[i + 1]
1250
+ )}}`;
1110
1251
  i += 2;
1111
1252
  }
1112
1253
  } else {
1113
1254
  if (i + 1 < childrenArray.length) {
1114
- postscripts += `_{${parse(childrenArray[i])}}^{${parse(childrenArray[i + 1])}}`;
1255
+ postscripts += `_{${parse(childrenArray[i])}}^{${parse(
1256
+ childrenArray[i + 1]
1257
+ )}}`;
1115
1258
  i += 2;
1116
1259
  } else break;
1117
1260
  }
@@ -1120,33 +1263,35 @@ function getRender(node) {
1120
1263
  };
1121
1264
  break;
1122
1265
 
1123
- case 'mlongdiv':
1266
+ case "mlongdiv":
1124
1267
  render = function (node, children) {
1125
1268
  const childrenArray = Array.from(children);
1126
- if (!childrenArray || childrenArray.length < 2) return '';
1127
- return `\\longdiv{${parse(childrenArray[0])}}{${parse(childrenArray[1])}}`;
1269
+ if (!childrenArray || childrenArray.length < 2) return "";
1270
+ return `\\longdiv{${parse(childrenArray[0])}}{${parse(
1271
+ childrenArray[1]
1272
+ )}}`;
1128
1273
  };
1129
1274
  break;
1130
1275
 
1131
- case 'mroot':
1276
+ case "mroot":
1132
1277
  render = function (node, children) {
1133
1278
  const childrenArray = Array.from(children);
1134
- if (!childrenArray || childrenArray.length < 2) return '';
1279
+ if (!childrenArray || childrenArray.length < 2) return "";
1135
1280
  const base = parse(childrenArray[0]);
1136
1281
  const index = parse(childrenArray[1]);
1137
1282
  return `\\sqrt[${index}]{${base}}`;
1138
1283
  };
1139
1284
  break;
1140
1285
 
1141
- case 'msqrt':
1286
+ case "msqrt":
1142
1287
  render = function (node, children) {
1143
1288
  const childrenArray = Array.from(children);
1144
- const content = renderChildren(childrenArray).join('');
1289
+ const content = renderChildren(childrenArray).join("");
1145
1290
  return `\\sqrt{${content}}`;
1146
1291
  };
1147
1292
  break;
1148
1293
 
1149
- case 'mtable':
1294
+ case "mtable":
1150
1295
  render = function (node, children) {
1151
1296
  const childrenArray = Array.from(children);
1152
1297
 
@@ -1154,7 +1299,7 @@ function getRender(node) {
1154
1299
  let isNestedTable = false;
1155
1300
  let parent = node.parentNode;
1156
1301
  while (parent) {
1157
- if (NodeTool.getNodeName(parent) === 'mtable') {
1302
+ if (NodeTool.getNodeName(parent) === "mtable") {
1158
1303
  isNestedTable = true;
1159
1304
  break;
1160
1305
  }
@@ -1162,25 +1307,27 @@ function getRender(node) {
1162
1307
  }
1163
1308
 
1164
1309
  // Xử lý mỗi mtr như một hàng
1165
- const rows = childrenArray.map(row => {
1310
+ const rows = childrenArray.map((row) => {
1166
1311
  const rowChildren = Array.from(NodeTool.getChildren(row));
1167
- return rowChildren.map(cell => parse(cell)).join('');
1312
+ return rowChildren.map((cell) => parse(cell)).join("");
1168
1313
  });
1169
1314
 
1170
1315
  // Nếu là mtable con, chỉ trả về các hàng mà không bao bọc trong \begin{array}...\end{array}
1171
1316
  if (isNestedTable) {
1172
- return rows.join(' \\\\ ');
1317
+ return rows.join(" \\\\ ");
1173
1318
  }
1174
1319
 
1175
1320
  // Nếu mtable nằm trong mrow với dấu ngoặc vuông, sẽ được xử lý ở mrow
1176
1321
  let isInsideSquareBrackets = false;
1177
1322
  parent = node.parentNode;
1178
1323
  while (parent) {
1179
- if (NodeTool.getNodeName(parent) === 'mrow') {
1324
+ if (NodeTool.getNodeName(parent) === "mrow") {
1180
1325
  const childrenOfParent = Array.from(NodeTool.getChildren(parent));
1181
- if (childrenOfParent.length >= 2 &&
1182
- NodeTool.getNodeName(childrenOfParent[0]) === 'mo' &&
1183
- NodeTool.getNodeText(childrenOfParent[0]).trim() === '[') {
1326
+ if (
1327
+ childrenOfParent.length >= 2 &&
1328
+ NodeTool.getNodeName(childrenOfParent[0]) === "mo" &&
1329
+ NodeTool.getNodeText(childrenOfParent[0]).trim() === "["
1330
+ ) {
1184
1331
  isInsideSquareBrackets = true;
1185
1332
  break;
1186
1333
  }
@@ -1189,151 +1336,166 @@ function getRender(node) {
1189
1336
  }
1190
1337
 
1191
1338
  if (isInsideSquareBrackets) {
1192
- return rows.join(' \\\\ ');
1339
+ return rows.join(" \\\\ ");
1193
1340
  }
1194
1341
 
1195
1342
  // Nếu là mtable chính, bao bọc trong \begin{array}...\end{array}
1196
- const arrayContent = rows.join(' \\\\ ');
1343
+ const arrayContent = rows.join(" \\\\ ");
1197
1344
  return `\\begin{array}{l} ${arrayContent} \\end{array}`;
1198
1345
  };
1199
1346
  break;
1200
1347
 
1201
- case 'mtr':
1348
+ case "mtr":
1202
1349
  render = getRender_joinSeparator("@content", " & ");
1203
1350
  break;
1204
1351
 
1205
- case 'mtd':
1352
+ case "mtd":
1206
1353
  render = getRender_joinSeparator("@content");
1207
1354
  break;
1208
1355
 
1209
- case 'mfrac':
1356
+ case "mfrac":
1210
1357
  render = function (node, children) {
1211
1358
  const childrenArray = Array.from(children);
1212
- if (!childrenArray || childrenArray.length < 2) return '';
1359
+ if (!childrenArray || childrenArray.length < 2) return "";
1213
1360
  const num = parse(childrenArray[0]);
1214
1361
  const den = parse(childrenArray[1]);
1215
- const linethickness = NodeTool.getAttr(node, 'linethickness', 'medium');
1216
- if (linethickness === '0') return `\\binom{${num}}{${den}}`;
1362
+ const linethickness = NodeTool.getAttr(node, "linethickness", "medium");
1363
+ if (linethickness === "0") return `\\binom{${num}}{${den}}`;
1217
1364
  return `\\frac{${num}}{${den}}`;
1218
1365
  };
1219
1366
  break;
1220
1367
 
1221
- case 'mfenced':
1368
+ case "mfenced":
1222
1369
  render = function (node, children) {
1223
1370
  const childrenArray = Array.from(children);
1224
- const open = NodeTool.getAttr(node, 'open', '(');
1225
- const close = NodeTool.getAttr(node, 'close', ')');
1226
- const separators = NodeTool.getAttr(node, 'separators', ',').split('');
1371
+ const open = NodeTool.getAttr(node, "open", "(");
1372
+ const close = NodeTool.getAttr(node, "close", ")");
1373
+ const separators = NodeTool.getAttr(node, "separators", ",").split("");
1227
1374
 
1228
1375
  // Xử lý đặc biệt cho trường hợp dấu ngoặc đơn |
1229
- if (open === '|') {
1230
- const content = childrenArray.map(child => {
1231
- const parsed = parse(child);
1232
- // Loại bỏ các dấu | thừa và các \left|, \right| không cần thiết
1233
- return parsed
1234
- .replace(/\\left\|/g, '')
1235
- .replace(/\\right\|/g, '')
1236
- .replace(/\\left\./g, '')
1237
- .replace(/\|/g, '');
1238
- }).join('');
1239
-
1376
+ if (open === "|") {
1377
+ const content = childrenArray
1378
+ .map((child) => {
1379
+ const parsed = parse(child);
1380
+ // Loại bỏ các dấu | thừa và các \left|, \right| không cần thiết
1381
+ return parsed
1382
+ .replace(/\\left\|/g, "")
1383
+ .replace(/\\right\|/g, "")
1384
+ .replace(/\\left\./g, "")
1385
+ .replace(/\|/g, "");
1386
+ })
1387
+ .join("");
1388
+
1240
1389
  if (!close) {
1241
1390
  return `\\left|${content}\\right|`;
1242
- } else if (close === '|') {
1391
+ } else if (close === "|") {
1243
1392
  return `\\left|${content}\\right|`;
1244
1393
  }
1245
1394
  }
1246
1395
 
1247
1396
  // Xử lý đặc biệt cho mfenced chứa mtable
1248
- if (open === '{' && !close) {
1397
+ if (open === "{" && !close) {
1249
1398
  // Kiểm tra xem có phải là một phần của biểu thức mũ không
1250
- const hasMtable = childrenArray.some(child => {
1399
+ const hasMtable = childrenArray.some((child) => {
1251
1400
  // Kiểm tra trực tiếp mtable
1252
- if (NodeTool.getNodeName(child) === 'mtable') return true;
1401
+ if (NodeTool.getNodeName(child) === "mtable") return true;
1253
1402
  // Kiểm tra mtable trong mrow
1254
- if (NodeTool.getNodeName(child) === 'mrow') {
1403
+ if (NodeTool.getNodeName(child) === "mrow") {
1255
1404
  return Array.from(NodeTool.getChildren(child)).some(
1256
- grandChild => NodeTool.getNodeName(grandChild) === 'mtable'
1405
+ (grandChild) => NodeTool.getNodeName(grandChild) === "mtable"
1257
1406
  );
1258
1407
  }
1259
1408
  return false;
1260
1409
  });
1261
1410
 
1262
1411
  if (hasMtable) {
1263
- const content = childrenArray.map(child => parse(child)).join('');
1412
+ const content = childrenArray.map((child) => parse(child)).join("");
1264
1413
  return `\\left\\{${content}\\right.`;
1265
1414
  }
1266
1415
  }
1267
1416
 
1268
1417
  // Xử lý cho trường hợp [a;b)
1269
- if (open === '[' && close === ')') {
1418
+ if (open === "[" && close === ")") {
1270
1419
  const parts = [];
1271
1420
  childrenArray.forEach((child, index) => {
1272
1421
  parts.push(parse(child));
1273
- if (index < childrenArray.length - 1 && separators[index % separators.length]) {
1422
+ if (
1423
+ index < childrenArray.length - 1 &&
1424
+ separators[index % separators.length]
1425
+ ) {
1274
1426
  parts.push(separators[index % separators.length]);
1275
1427
  }
1276
1428
  });
1277
- return `\\left[${parts.join('')}\\right)`;
1429
+ return `\\left[${parts.join("")}\\right)`;
1278
1430
  }
1279
1431
 
1280
1432
  // Giữ nguyên xử lý cho các trường hợp khác
1281
1433
  const parts = [];
1282
1434
  childrenArray.forEach((child, index) => {
1283
1435
  parts.push(parse(child));
1284
- if (index < childrenArray.length - 1 && separators[index % separators.length]) {
1436
+ if (
1437
+ index < childrenArray.length - 1 &&
1438
+ separators[index % separators.length]
1439
+ ) {
1285
1440
  parts.push(separators[index % separators.length]);
1286
1441
  }
1287
1442
  });
1288
- const content = parts.join('');
1443
+ const content = parts.join("");
1289
1444
 
1290
- if (open === '{' && close === '}') return `\\{${content}\\}`;
1291
- if (open === '|' && close === '|') return `\\left|${content}\\right|`;
1445
+ if (open === "{" && close === "}") return `\\{${content}\\}`;
1446
+ if (open === "|" && close === "|") return `\\left|${content}\\right|`;
1292
1447
  if (!close) return `\\left${open}${content}\\right.`;
1293
1448
  if (!open) return `\\left.${content}\\right${close}`;
1294
1449
  return `\\left${open}${content}\\right${close}`;
1295
1450
  };
1296
1451
  break;
1297
1452
 
1298
- case 'menclose':
1453
+ case "menclose":
1299
1454
  render = function (node, children) {
1300
1455
  const childrenArray = Array.from(children);
1301
- const notation = NodeTool.getAttr(node, 'notation', 'longdiv');
1302
- const content = renderChildren(childrenArray).join('');
1456
+ const notation = NodeTool.getAttr(node, "notation", "longdiv");
1457
+ const content = renderChildren(childrenArray).join("");
1303
1458
  switch (notation) {
1304
- case 'box': return `\\boxed{${content}}`;
1305
- case 'circle': return `\\enclose{circle}{${content}}`;
1306
- case 'roundedbox': return `\\fbox{${content}}`;
1307
- default: return content;
1459
+ case "box":
1460
+ return `\\boxed{${content}}`;
1461
+ case "circle":
1462
+ return `\\enclose{circle}{${content}}`;
1463
+ case "roundedbox":
1464
+ return `\\fbox{${content}}`;
1465
+ default:
1466
+ return content;
1308
1467
  }
1309
1468
  };
1310
1469
  break;
1311
1470
 
1312
- case 'mi':
1313
- case 'mn':
1314
- case 'mo':
1315
- case 'ms':
1316
- case 'mtext':
1471
+ case "mi":
1472
+ case "mn":
1473
+ case "mo":
1474
+ case "ms":
1475
+ case "mtext":
1317
1476
  render = getRender_joinSeparator("@content");
1318
1477
  break;
1319
1478
 
1320
- case 'mphantom':
1479
+ case "mphantom":
1321
1480
  render = function (node, children) {
1322
1481
  const childrenArray = Array.from(children);
1323
- const content = renderChildren(childrenArray).join('');
1482
+ const content = renderChildren(childrenArray).join("");
1324
1483
  return `\\phantom{${content}}`;
1325
1484
  };
1326
1485
  break;
1327
1486
 
1328
- case 'mstyle':
1487
+ case "mstyle":
1329
1488
  render = function (node, children) {
1330
1489
  const childrenArray = Array.from(children);
1331
- const mathsize = NodeTool.getAttr(node, 'mathsize', 'normal');
1332
- const content = renderChildren(childrenArray).join('');
1490
+ const mathsize = NodeTool.getAttr(node, "mathsize", "normal");
1491
+ const content = renderChildren(childrenArray).join("");
1333
1492
  switch (mathsize) {
1334
- case 'big': return `\\large{${content}}`;
1335
- case 'small': return `\\small{${content}}`;
1336
- default: return content;
1493
+ case "big":
1494
+ return `\\large{${content}}`;
1495
+ case "small":
1496
+ return `\\small{${content}}`;
1497
+ default:
1498
+ return content;
1337
1499
  }
1338
1500
  };
1339
1501
  break;
@@ -1347,7 +1509,7 @@ function getRender(node) {
1347
1509
 
1348
1510
  // Export the convert function
1349
1511
  var mathml2latex = {
1350
- convert: convert
1512
+ convert: convert,
1351
1513
  };
1352
1514
 
1353
1515
  export default mathml2latex;