ed-mathml2tex 0.2.1 → 0.2.3
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 +47 -23
- package/lib/mathml2latex.browser.es.js +47 -23
- package/lib/mathml2latex.browser.umd.js +47 -23
- package/lib/mathml2latex.cjs.js +47 -23
- package/lib/mathml2latex.es.js +47 -23
- package/lib/mathml2latex.umd.js +47 -23
- package/package.json +1 -1
|
@@ -277,24 +277,24 @@ const MathSymbol = {
|
|
|
277
277
|
bigCommand: {
|
|
278
278
|
decimals: [8721, 8719, 8720, 10753, 10754, 10752, 8899, 8898, 10756, 10758, 8897, 8896, 8747, 8750, 8748, 8749, 10764, 8747],
|
|
279
279
|
scripts: [
|
|
280
|
-
"\\sum",
|
|
281
|
-
"\\prod",
|
|
282
|
-
"\\coprod",
|
|
283
|
-
"\\bigoplus",
|
|
284
|
-
"\\bigotimes",
|
|
285
|
-
"\\bigodot",
|
|
286
|
-
"\\bigcup",
|
|
287
|
-
"\\bigcap",
|
|
288
|
-
"\\biguplus",
|
|
289
|
-
"\\bigsqcup",
|
|
290
|
-
"\\bigvee",
|
|
291
|
-
"\\bigwedge",
|
|
292
|
-
"\\int",
|
|
293
|
-
"\\oint",
|
|
294
|
-
"\\iint",
|
|
295
|
-
"\\iiint",
|
|
296
|
-
"\\iiiint",
|
|
297
|
-
"\\idotsint",
|
|
280
|
+
"\\sum ",
|
|
281
|
+
"\\prod ",
|
|
282
|
+
"\\coprod ",
|
|
283
|
+
"\\bigoplus ",
|
|
284
|
+
"\\bigotimes ",
|
|
285
|
+
"\\bigodot ",
|
|
286
|
+
"\\bigcup ",
|
|
287
|
+
"\\bigcap ",
|
|
288
|
+
"\\biguplus ",
|
|
289
|
+
"\\bigsqcup ",
|
|
290
|
+
"\\bigvee ",
|
|
291
|
+
"\\bigwedge ",
|
|
292
|
+
"\\int ",
|
|
293
|
+
"\\oint ",
|
|
294
|
+
"\\iint ",
|
|
295
|
+
"\\iiint ",
|
|
296
|
+
"\\iiiint ",
|
|
297
|
+
"\\idotsint ",
|
|
298
298
|
]
|
|
299
299
|
},
|
|
300
300
|
|
|
@@ -612,9 +612,10 @@ function convert(mathmlHtml) {
|
|
|
612
612
|
// Thêm xử lý cho các thẻ MathML khác
|
|
613
613
|
result = result
|
|
614
614
|
.replace(/∞/g, "\\infty") // Vô cực
|
|
615
|
-
.replace(
|
|
616
|
-
|
|
617
|
-
|
|
615
|
+
.replace(/∫/g, " \\int "); // Tích phân
|
|
616
|
+
|
|
617
|
+
// Đảm bảo dấu cách sau các lệnh LaTeX quan trọng để tránh dính biến (vd: \intf -> \int f)
|
|
618
|
+
result = result.replace(/\\(int|sum|prod|cos|sin|tan|cot|lim|log|ln)([a-zA-Z0-9])/g, "\\$1 $2");
|
|
618
619
|
|
|
619
620
|
return result;
|
|
620
621
|
}
|
|
@@ -773,7 +774,8 @@ function parseOperator(node) {
|
|
|
773
774
|
"|": " \\mid ", // PATCH: set-builder mid
|
|
774
775
|
π: " \\pi ", // PATCH: Greek letter
|
|
775
776
|
};
|
|
776
|
-
|
|
777
|
+
const res = operatorMap[it] || escapeSpecialChars(MathSymbol.parseOperator(it));
|
|
778
|
+
return res;
|
|
777
779
|
}
|
|
778
780
|
// --- END PATCH ---
|
|
779
781
|
|
|
@@ -800,6 +802,20 @@ function parseElementMi(node) {
|
|
|
800
802
|
// Math Number
|
|
801
803
|
function parseElementMn(node) {
|
|
802
804
|
let it = NodeTool.getNodeText(node).trim();
|
|
805
|
+
// Loại bỏ các ký tự điều khiển hoặc khoảng trắng lạ
|
|
806
|
+
it = it.replace(/[\u0000-\u001F\u007F-\u009F\u00A0]/g, "");
|
|
807
|
+
|
|
808
|
+
// Danh sách các hàm toán học mở rộng
|
|
809
|
+
const mathFunctions = ["cos", "sin", "tan", "cot", "arccos", "arcsin", "arctan", "arccot", "log", "ln", "lim", "sinh", "cosh", "tanh", "sec", "csc"];
|
|
810
|
+
|
|
811
|
+
if (mathFunctions.some(fn => it.toLowerCase().includes(fn))) {
|
|
812
|
+
// Tìm hàm khớp chính xác nhất
|
|
813
|
+
for (const fn of mathFunctions) {
|
|
814
|
+
if (it.toLowerCase() === fn) {
|
|
815
|
+
return "\\" + fn + " ";
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
803
819
|
return escapeSpecialChars(it);
|
|
804
820
|
}
|
|
805
821
|
|
|
@@ -812,7 +828,7 @@ function parseElementMs(node) {
|
|
|
812
828
|
|
|
813
829
|
// Math Text
|
|
814
830
|
function parseElementMtext(node) {
|
|
815
|
-
let content = NodeTool.getNodeText(node)
|
|
831
|
+
let content = escapeSpecialChars(NodeTool.getNodeText(node))
|
|
816
832
|
.replace(/\s*=\s*/g, " = ")
|
|
817
833
|
.replace(/\s*\.\s*/g, " \\cdot ")
|
|
818
834
|
.trim();
|
|
@@ -866,6 +882,14 @@ function parseElementMspace(node) {
|
|
|
866
882
|
}
|
|
867
883
|
|
|
868
884
|
function escapeSpecialChars(text) {
|
|
885
|
+
// Strip problematic Unicode characters:
|
|
886
|
+
// - Control characters: \u0000-\u0008, \u000B-\u000C, \u000E-\u001F, \u007F-\u009F
|
|
887
|
+
// - Zero-width & Invisible: \u200B-\u200F, \u202A-\u202E, \u2060-\u206F, \uFEFF
|
|
888
|
+
// - Variation Selectors: \uFE00-\uFE0F
|
|
889
|
+
// - Private Use Area (PUA): \uE000-\uF8FF
|
|
890
|
+
// - Non-characters: \uFDD0-\uFDEF
|
|
891
|
+
text = text.replace(/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFE00-\uFE0F\uFEFF\uE000-\uF8FF\uFDD0-\uFDEF]/g, "");
|
|
892
|
+
|
|
869
893
|
// Don't escape pi, Greek, or just a-z0-9 or Unicode Greek, or empty
|
|
870
894
|
if (
|
|
871
895
|
/^\\?[a-zA-Z0-9]+$/.test(text) ||
|
|
@@ -275,24 +275,24 @@ const MathSymbol = {
|
|
|
275
275
|
bigCommand: {
|
|
276
276
|
decimals: [8721, 8719, 8720, 10753, 10754, 10752, 8899, 8898, 10756, 10758, 8897, 8896, 8747, 8750, 8748, 8749, 10764, 8747],
|
|
277
277
|
scripts: [
|
|
278
|
-
"\\sum",
|
|
279
|
-
"\\prod",
|
|
280
|
-
"\\coprod",
|
|
281
|
-
"\\bigoplus",
|
|
282
|
-
"\\bigotimes",
|
|
283
|
-
"\\bigodot",
|
|
284
|
-
"\\bigcup",
|
|
285
|
-
"\\bigcap",
|
|
286
|
-
"\\biguplus",
|
|
287
|
-
"\\bigsqcup",
|
|
288
|
-
"\\bigvee",
|
|
289
|
-
"\\bigwedge",
|
|
290
|
-
"\\int",
|
|
291
|
-
"\\oint",
|
|
292
|
-
"\\iint",
|
|
293
|
-
"\\iiint",
|
|
294
|
-
"\\iiiint",
|
|
295
|
-
"\\idotsint",
|
|
278
|
+
"\\sum ",
|
|
279
|
+
"\\prod ",
|
|
280
|
+
"\\coprod ",
|
|
281
|
+
"\\bigoplus ",
|
|
282
|
+
"\\bigotimes ",
|
|
283
|
+
"\\bigodot ",
|
|
284
|
+
"\\bigcup ",
|
|
285
|
+
"\\bigcap ",
|
|
286
|
+
"\\biguplus ",
|
|
287
|
+
"\\bigsqcup ",
|
|
288
|
+
"\\bigvee ",
|
|
289
|
+
"\\bigwedge ",
|
|
290
|
+
"\\int ",
|
|
291
|
+
"\\oint ",
|
|
292
|
+
"\\iint ",
|
|
293
|
+
"\\iiint ",
|
|
294
|
+
"\\iiiint ",
|
|
295
|
+
"\\idotsint ",
|
|
296
296
|
]
|
|
297
297
|
},
|
|
298
298
|
|
|
@@ -610,9 +610,10 @@ function convert(mathmlHtml) {
|
|
|
610
610
|
// Thêm xử lý cho các thẻ MathML khác
|
|
611
611
|
result = result
|
|
612
612
|
.replace(/∞/g, "\\infty") // Vô cực
|
|
613
|
-
.replace(
|
|
614
|
-
|
|
615
|
-
|
|
613
|
+
.replace(/∫/g, " \\int "); // Tích phân
|
|
614
|
+
|
|
615
|
+
// Đảm bảo dấu cách sau các lệnh LaTeX quan trọng để tránh dính biến (vd: \intf -> \int f)
|
|
616
|
+
result = result.replace(/\\(int|sum|prod|cos|sin|tan|cot|lim|log|ln)([a-zA-Z0-9])/g, "\\$1 $2");
|
|
616
617
|
|
|
617
618
|
return result;
|
|
618
619
|
}
|
|
@@ -771,7 +772,8 @@ function parseOperator(node) {
|
|
|
771
772
|
"|": " \\mid ", // PATCH: set-builder mid
|
|
772
773
|
π: " \\pi ", // PATCH: Greek letter
|
|
773
774
|
};
|
|
774
|
-
|
|
775
|
+
const res = operatorMap[it] || escapeSpecialChars(MathSymbol.parseOperator(it));
|
|
776
|
+
return res;
|
|
775
777
|
}
|
|
776
778
|
// --- END PATCH ---
|
|
777
779
|
|
|
@@ -798,6 +800,20 @@ function parseElementMi(node) {
|
|
|
798
800
|
// Math Number
|
|
799
801
|
function parseElementMn(node) {
|
|
800
802
|
let it = NodeTool.getNodeText(node).trim();
|
|
803
|
+
// Loại bỏ các ký tự điều khiển hoặc khoảng trắng lạ
|
|
804
|
+
it = it.replace(/[\u0000-\u001F\u007F-\u009F\u00A0]/g, "");
|
|
805
|
+
|
|
806
|
+
// Danh sách các hàm toán học mở rộng
|
|
807
|
+
const mathFunctions = ["cos", "sin", "tan", "cot", "arccos", "arcsin", "arctan", "arccot", "log", "ln", "lim", "sinh", "cosh", "tanh", "sec", "csc"];
|
|
808
|
+
|
|
809
|
+
if (mathFunctions.some(fn => it.toLowerCase().includes(fn))) {
|
|
810
|
+
// Tìm hàm khớp chính xác nhất
|
|
811
|
+
for (const fn of mathFunctions) {
|
|
812
|
+
if (it.toLowerCase() === fn) {
|
|
813
|
+
return "\\" + fn + " ";
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
801
817
|
return escapeSpecialChars(it);
|
|
802
818
|
}
|
|
803
819
|
|
|
@@ -810,7 +826,7 @@ function parseElementMs(node) {
|
|
|
810
826
|
|
|
811
827
|
// Math Text
|
|
812
828
|
function parseElementMtext(node) {
|
|
813
|
-
let content = NodeTool.getNodeText(node)
|
|
829
|
+
let content = escapeSpecialChars(NodeTool.getNodeText(node))
|
|
814
830
|
.replace(/\s*=\s*/g, " = ")
|
|
815
831
|
.replace(/\s*\.\s*/g, " \\cdot ")
|
|
816
832
|
.trim();
|
|
@@ -864,6 +880,14 @@ function parseElementMspace(node) {
|
|
|
864
880
|
}
|
|
865
881
|
|
|
866
882
|
function escapeSpecialChars(text) {
|
|
883
|
+
// Strip problematic Unicode characters:
|
|
884
|
+
// - Control characters: \u0000-\u0008, \u000B-\u000C, \u000E-\u001F, \u007F-\u009F
|
|
885
|
+
// - Zero-width & Invisible: \u200B-\u200F, \u202A-\u202E, \u2060-\u206F, \uFEFF
|
|
886
|
+
// - Variation Selectors: \uFE00-\uFE0F
|
|
887
|
+
// - Private Use Area (PUA): \uE000-\uF8FF
|
|
888
|
+
// - Non-characters: \uFDD0-\uFDEF
|
|
889
|
+
text = text.replace(/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFE00-\uFE0F\uFEFF\uE000-\uF8FF\uFDD0-\uFDEF]/g, "");
|
|
890
|
+
|
|
867
891
|
// Don't escape pi, Greek, or just a-z0-9 or Unicode Greek, or empty
|
|
868
892
|
if (
|
|
869
893
|
/^\\?[a-zA-Z0-9]+$/.test(text) ||
|
|
@@ -281,24 +281,24 @@
|
|
|
281
281
|
bigCommand: {
|
|
282
282
|
decimals: [8721, 8719, 8720, 10753, 10754, 10752, 8899, 8898, 10756, 10758, 8897, 8896, 8747, 8750, 8748, 8749, 10764, 8747],
|
|
283
283
|
scripts: [
|
|
284
|
-
"\\sum",
|
|
285
|
-
"\\prod",
|
|
286
|
-
"\\coprod",
|
|
287
|
-
"\\bigoplus",
|
|
288
|
-
"\\bigotimes",
|
|
289
|
-
"\\bigodot",
|
|
290
|
-
"\\bigcup",
|
|
291
|
-
"\\bigcap",
|
|
292
|
-
"\\biguplus",
|
|
293
|
-
"\\bigsqcup",
|
|
294
|
-
"\\bigvee",
|
|
295
|
-
"\\bigwedge",
|
|
296
|
-
"\\int",
|
|
297
|
-
"\\oint",
|
|
298
|
-
"\\iint",
|
|
299
|
-
"\\iiint",
|
|
300
|
-
"\\iiiint",
|
|
301
|
-
"\\idotsint",
|
|
284
|
+
"\\sum ",
|
|
285
|
+
"\\prod ",
|
|
286
|
+
"\\coprod ",
|
|
287
|
+
"\\bigoplus ",
|
|
288
|
+
"\\bigotimes ",
|
|
289
|
+
"\\bigodot ",
|
|
290
|
+
"\\bigcup ",
|
|
291
|
+
"\\bigcap ",
|
|
292
|
+
"\\biguplus ",
|
|
293
|
+
"\\bigsqcup ",
|
|
294
|
+
"\\bigvee ",
|
|
295
|
+
"\\bigwedge ",
|
|
296
|
+
"\\int ",
|
|
297
|
+
"\\oint ",
|
|
298
|
+
"\\iint ",
|
|
299
|
+
"\\iiint ",
|
|
300
|
+
"\\iiiint ",
|
|
301
|
+
"\\idotsint ",
|
|
302
302
|
]
|
|
303
303
|
},
|
|
304
304
|
|
|
@@ -616,9 +616,10 @@
|
|
|
616
616
|
// Thêm xử lý cho các thẻ MathML khác
|
|
617
617
|
result = result
|
|
618
618
|
.replace(/∞/g, "\\infty") // Vô cực
|
|
619
|
-
.replace(
|
|
620
|
-
|
|
621
|
-
|
|
619
|
+
.replace(/∫/g, " \\int "); // Tích phân
|
|
620
|
+
|
|
621
|
+
// Đảm bảo dấu cách sau các lệnh LaTeX quan trọng để tránh dính biến (vd: \intf -> \int f)
|
|
622
|
+
result = result.replace(/\\(int|sum|prod|cos|sin|tan|cot|lim|log|ln)([a-zA-Z0-9])/g, "\\$1 $2");
|
|
622
623
|
|
|
623
624
|
return result;
|
|
624
625
|
}
|
|
@@ -777,7 +778,8 @@
|
|
|
777
778
|
"|": " \\mid ", // PATCH: set-builder mid
|
|
778
779
|
π: " \\pi ", // PATCH: Greek letter
|
|
779
780
|
};
|
|
780
|
-
|
|
781
|
+
const res = operatorMap[it] || escapeSpecialChars(MathSymbol.parseOperator(it));
|
|
782
|
+
return res;
|
|
781
783
|
}
|
|
782
784
|
// --- END PATCH ---
|
|
783
785
|
|
|
@@ -804,6 +806,20 @@
|
|
|
804
806
|
// Math Number
|
|
805
807
|
function parseElementMn(node) {
|
|
806
808
|
let it = NodeTool.getNodeText(node).trim();
|
|
809
|
+
// Loại bỏ các ký tự điều khiển hoặc khoảng trắng lạ
|
|
810
|
+
it = it.replace(/[\u0000-\u001F\u007F-\u009F\u00A0]/g, "");
|
|
811
|
+
|
|
812
|
+
// Danh sách các hàm toán học mở rộng
|
|
813
|
+
const mathFunctions = ["cos", "sin", "tan", "cot", "arccos", "arcsin", "arctan", "arccot", "log", "ln", "lim", "sinh", "cosh", "tanh", "sec", "csc"];
|
|
814
|
+
|
|
815
|
+
if (mathFunctions.some(fn => it.toLowerCase().includes(fn))) {
|
|
816
|
+
// Tìm hàm khớp chính xác nhất
|
|
817
|
+
for (const fn of mathFunctions) {
|
|
818
|
+
if (it.toLowerCase() === fn) {
|
|
819
|
+
return "\\" + fn + " ";
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
807
823
|
return escapeSpecialChars(it);
|
|
808
824
|
}
|
|
809
825
|
|
|
@@ -816,7 +832,7 @@
|
|
|
816
832
|
|
|
817
833
|
// Math Text
|
|
818
834
|
function parseElementMtext(node) {
|
|
819
|
-
let content = NodeTool.getNodeText(node)
|
|
835
|
+
let content = escapeSpecialChars(NodeTool.getNodeText(node))
|
|
820
836
|
.replace(/\s*=\s*/g, " = ")
|
|
821
837
|
.replace(/\s*\.\s*/g, " \\cdot ")
|
|
822
838
|
.trim();
|
|
@@ -870,6 +886,14 @@
|
|
|
870
886
|
}
|
|
871
887
|
|
|
872
888
|
function escapeSpecialChars(text) {
|
|
889
|
+
// Strip problematic Unicode characters:
|
|
890
|
+
// - Control characters: \u0000-\u0008, \u000B-\u000C, \u000E-\u001F, \u007F-\u009F
|
|
891
|
+
// - Zero-width & Invisible: \u200B-\u200F, \u202A-\u202E, \u2060-\u206F, \uFEFF
|
|
892
|
+
// - Variation Selectors: \uFE00-\uFE0F
|
|
893
|
+
// - Private Use Area (PUA): \uE000-\uF8FF
|
|
894
|
+
// - Non-characters: \uFDD0-\uFDEF
|
|
895
|
+
text = text.replace(/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFE00-\uFE0F\uFEFF\uE000-\uF8FF\uFDD0-\uFDEF]/g, "");
|
|
896
|
+
|
|
873
897
|
// Don't escape pi, Greek, or just a-z0-9 or Unicode Greek, or empty
|
|
874
898
|
if (
|
|
875
899
|
/^\\?[a-zA-Z0-9]+$/.test(text) ||
|
package/lib/mathml2latex.cjs.js
CHANGED
|
@@ -277,24 +277,24 @@ const MathSymbol = {
|
|
|
277
277
|
bigCommand: {
|
|
278
278
|
decimals: [8721, 8719, 8720, 10753, 10754, 10752, 8899, 8898, 10756, 10758, 8897, 8896, 8747, 8750, 8748, 8749, 10764, 8747],
|
|
279
279
|
scripts: [
|
|
280
|
-
"\\sum",
|
|
281
|
-
"\\prod",
|
|
282
|
-
"\\coprod",
|
|
283
|
-
"\\bigoplus",
|
|
284
|
-
"\\bigotimes",
|
|
285
|
-
"\\bigodot",
|
|
286
|
-
"\\bigcup",
|
|
287
|
-
"\\bigcap",
|
|
288
|
-
"\\biguplus",
|
|
289
|
-
"\\bigsqcup",
|
|
290
|
-
"\\bigvee",
|
|
291
|
-
"\\bigwedge",
|
|
292
|
-
"\\int",
|
|
293
|
-
"\\oint",
|
|
294
|
-
"\\iint",
|
|
295
|
-
"\\iiint",
|
|
296
|
-
"\\iiiint",
|
|
297
|
-
"\\idotsint",
|
|
280
|
+
"\\sum ",
|
|
281
|
+
"\\prod ",
|
|
282
|
+
"\\coprod ",
|
|
283
|
+
"\\bigoplus ",
|
|
284
|
+
"\\bigotimes ",
|
|
285
|
+
"\\bigodot ",
|
|
286
|
+
"\\bigcup ",
|
|
287
|
+
"\\bigcap ",
|
|
288
|
+
"\\biguplus ",
|
|
289
|
+
"\\bigsqcup ",
|
|
290
|
+
"\\bigvee ",
|
|
291
|
+
"\\bigwedge ",
|
|
292
|
+
"\\int ",
|
|
293
|
+
"\\oint ",
|
|
294
|
+
"\\iint ",
|
|
295
|
+
"\\iiint ",
|
|
296
|
+
"\\iiiint ",
|
|
297
|
+
"\\idotsint ",
|
|
298
298
|
]
|
|
299
299
|
},
|
|
300
300
|
|
|
@@ -612,9 +612,10 @@ function convert(mathmlHtml) {
|
|
|
612
612
|
// Thêm xử lý cho các thẻ MathML khác
|
|
613
613
|
result = result
|
|
614
614
|
.replace(/∞/g, "\\infty") // Vô cực
|
|
615
|
-
.replace(
|
|
616
|
-
|
|
617
|
-
|
|
615
|
+
.replace(/∫/g, " \\int "); // Tích phân
|
|
616
|
+
|
|
617
|
+
// Đảm bảo dấu cách sau các lệnh LaTeX quan trọng để tránh dính biến (vd: \intf -> \int f)
|
|
618
|
+
result = result.replace(/\\(int|sum|prod|cos|sin|tan|cot|lim|log|ln)([a-zA-Z0-9])/g, "\\$1 $2");
|
|
618
619
|
|
|
619
620
|
return result;
|
|
620
621
|
}
|
|
@@ -773,7 +774,8 @@ function parseOperator(node) {
|
|
|
773
774
|
"|": " \\mid ", // PATCH: set-builder mid
|
|
774
775
|
π: " \\pi ", // PATCH: Greek letter
|
|
775
776
|
};
|
|
776
|
-
|
|
777
|
+
const res = operatorMap[it] || escapeSpecialChars(MathSymbol.parseOperator(it));
|
|
778
|
+
return res;
|
|
777
779
|
}
|
|
778
780
|
// --- END PATCH ---
|
|
779
781
|
|
|
@@ -800,6 +802,20 @@ function parseElementMi(node) {
|
|
|
800
802
|
// Math Number
|
|
801
803
|
function parseElementMn(node) {
|
|
802
804
|
let it = NodeTool.getNodeText(node).trim();
|
|
805
|
+
// Loại bỏ các ký tự điều khiển hoặc khoảng trắng lạ
|
|
806
|
+
it = it.replace(/[\u0000-\u001F\u007F-\u009F\u00A0]/g, "");
|
|
807
|
+
|
|
808
|
+
// Danh sách các hàm toán học mở rộng
|
|
809
|
+
const mathFunctions = ["cos", "sin", "tan", "cot", "arccos", "arcsin", "arctan", "arccot", "log", "ln", "lim", "sinh", "cosh", "tanh", "sec", "csc"];
|
|
810
|
+
|
|
811
|
+
if (mathFunctions.some(fn => it.toLowerCase().includes(fn))) {
|
|
812
|
+
// Tìm hàm khớp chính xác nhất
|
|
813
|
+
for (const fn of mathFunctions) {
|
|
814
|
+
if (it.toLowerCase() === fn) {
|
|
815
|
+
return "\\" + fn + " ";
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
803
819
|
return escapeSpecialChars(it);
|
|
804
820
|
}
|
|
805
821
|
|
|
@@ -812,7 +828,7 @@ function parseElementMs(node) {
|
|
|
812
828
|
|
|
813
829
|
// Math Text
|
|
814
830
|
function parseElementMtext(node) {
|
|
815
|
-
let content = NodeTool.getNodeText(node)
|
|
831
|
+
let content = escapeSpecialChars(NodeTool.getNodeText(node))
|
|
816
832
|
.replace(/\s*=\s*/g, " = ")
|
|
817
833
|
.replace(/\s*\.\s*/g, " \\cdot ")
|
|
818
834
|
.trim();
|
|
@@ -866,6 +882,14 @@ function parseElementMspace(node) {
|
|
|
866
882
|
}
|
|
867
883
|
|
|
868
884
|
function escapeSpecialChars(text) {
|
|
885
|
+
// Strip problematic Unicode characters:
|
|
886
|
+
// - Control characters: \u0000-\u0008, \u000B-\u000C, \u000E-\u001F, \u007F-\u009F
|
|
887
|
+
// - Zero-width & Invisible: \u200B-\u200F, \u202A-\u202E, \u2060-\u206F, \uFEFF
|
|
888
|
+
// - Variation Selectors: \uFE00-\uFE0F
|
|
889
|
+
// - Private Use Area (PUA): \uE000-\uF8FF
|
|
890
|
+
// - Non-characters: \uFDD0-\uFDEF
|
|
891
|
+
text = text.replace(/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFE00-\uFE0F\uFEFF\uE000-\uF8FF\uFDD0-\uFDEF]/g, "");
|
|
892
|
+
|
|
869
893
|
// Don't escape pi, Greek, or just a-z0-9 or Unicode Greek, or empty
|
|
870
894
|
if (
|
|
871
895
|
/^\\?[a-zA-Z0-9]+$/.test(text) ||
|
package/lib/mathml2latex.es.js
CHANGED
|
@@ -275,24 +275,24 @@ const MathSymbol = {
|
|
|
275
275
|
bigCommand: {
|
|
276
276
|
decimals: [8721, 8719, 8720, 10753, 10754, 10752, 8899, 8898, 10756, 10758, 8897, 8896, 8747, 8750, 8748, 8749, 10764, 8747],
|
|
277
277
|
scripts: [
|
|
278
|
-
"\\sum",
|
|
279
|
-
"\\prod",
|
|
280
|
-
"\\coprod",
|
|
281
|
-
"\\bigoplus",
|
|
282
|
-
"\\bigotimes",
|
|
283
|
-
"\\bigodot",
|
|
284
|
-
"\\bigcup",
|
|
285
|
-
"\\bigcap",
|
|
286
|
-
"\\biguplus",
|
|
287
|
-
"\\bigsqcup",
|
|
288
|
-
"\\bigvee",
|
|
289
|
-
"\\bigwedge",
|
|
290
|
-
"\\int",
|
|
291
|
-
"\\oint",
|
|
292
|
-
"\\iint",
|
|
293
|
-
"\\iiint",
|
|
294
|
-
"\\iiiint",
|
|
295
|
-
"\\idotsint",
|
|
278
|
+
"\\sum ",
|
|
279
|
+
"\\prod ",
|
|
280
|
+
"\\coprod ",
|
|
281
|
+
"\\bigoplus ",
|
|
282
|
+
"\\bigotimes ",
|
|
283
|
+
"\\bigodot ",
|
|
284
|
+
"\\bigcup ",
|
|
285
|
+
"\\bigcap ",
|
|
286
|
+
"\\biguplus ",
|
|
287
|
+
"\\bigsqcup ",
|
|
288
|
+
"\\bigvee ",
|
|
289
|
+
"\\bigwedge ",
|
|
290
|
+
"\\int ",
|
|
291
|
+
"\\oint ",
|
|
292
|
+
"\\iint ",
|
|
293
|
+
"\\iiint ",
|
|
294
|
+
"\\iiiint ",
|
|
295
|
+
"\\idotsint ",
|
|
296
296
|
]
|
|
297
297
|
},
|
|
298
298
|
|
|
@@ -610,9 +610,10 @@ function convert(mathmlHtml) {
|
|
|
610
610
|
// Thêm xử lý cho các thẻ MathML khác
|
|
611
611
|
result = result
|
|
612
612
|
.replace(/∞/g, "\\infty") // Vô cực
|
|
613
|
-
.replace(
|
|
614
|
-
|
|
615
|
-
|
|
613
|
+
.replace(/∫/g, " \\int "); // Tích phân
|
|
614
|
+
|
|
615
|
+
// Đảm bảo dấu cách sau các lệnh LaTeX quan trọng để tránh dính biến (vd: \intf -> \int f)
|
|
616
|
+
result = result.replace(/\\(int|sum|prod|cos|sin|tan|cot|lim|log|ln)([a-zA-Z0-9])/g, "\\$1 $2");
|
|
616
617
|
|
|
617
618
|
return result;
|
|
618
619
|
}
|
|
@@ -771,7 +772,8 @@ function parseOperator(node) {
|
|
|
771
772
|
"|": " \\mid ", // PATCH: set-builder mid
|
|
772
773
|
π: " \\pi ", // PATCH: Greek letter
|
|
773
774
|
};
|
|
774
|
-
|
|
775
|
+
const res = operatorMap[it] || escapeSpecialChars(MathSymbol.parseOperator(it));
|
|
776
|
+
return res;
|
|
775
777
|
}
|
|
776
778
|
// --- END PATCH ---
|
|
777
779
|
|
|
@@ -798,6 +800,20 @@ function parseElementMi(node) {
|
|
|
798
800
|
// Math Number
|
|
799
801
|
function parseElementMn(node) {
|
|
800
802
|
let it = NodeTool.getNodeText(node).trim();
|
|
803
|
+
// Loại bỏ các ký tự điều khiển hoặc khoảng trắng lạ
|
|
804
|
+
it = it.replace(/[\u0000-\u001F\u007F-\u009F\u00A0]/g, "");
|
|
805
|
+
|
|
806
|
+
// Danh sách các hàm toán học mở rộng
|
|
807
|
+
const mathFunctions = ["cos", "sin", "tan", "cot", "arccos", "arcsin", "arctan", "arccot", "log", "ln", "lim", "sinh", "cosh", "tanh", "sec", "csc"];
|
|
808
|
+
|
|
809
|
+
if (mathFunctions.some(fn => it.toLowerCase().includes(fn))) {
|
|
810
|
+
// Tìm hàm khớp chính xác nhất
|
|
811
|
+
for (const fn of mathFunctions) {
|
|
812
|
+
if (it.toLowerCase() === fn) {
|
|
813
|
+
return "\\" + fn + " ";
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
801
817
|
return escapeSpecialChars(it);
|
|
802
818
|
}
|
|
803
819
|
|
|
@@ -810,7 +826,7 @@ function parseElementMs(node) {
|
|
|
810
826
|
|
|
811
827
|
// Math Text
|
|
812
828
|
function parseElementMtext(node) {
|
|
813
|
-
let content = NodeTool.getNodeText(node)
|
|
829
|
+
let content = escapeSpecialChars(NodeTool.getNodeText(node))
|
|
814
830
|
.replace(/\s*=\s*/g, " = ")
|
|
815
831
|
.replace(/\s*\.\s*/g, " \\cdot ")
|
|
816
832
|
.trim();
|
|
@@ -864,6 +880,14 @@ function parseElementMspace(node) {
|
|
|
864
880
|
}
|
|
865
881
|
|
|
866
882
|
function escapeSpecialChars(text) {
|
|
883
|
+
// Strip problematic Unicode characters:
|
|
884
|
+
// - Control characters: \u0000-\u0008, \u000B-\u000C, \u000E-\u001F, \u007F-\u009F
|
|
885
|
+
// - Zero-width & Invisible: \u200B-\u200F, \u202A-\u202E, \u2060-\u206F, \uFEFF
|
|
886
|
+
// - Variation Selectors: \uFE00-\uFE0F
|
|
887
|
+
// - Private Use Area (PUA): \uE000-\uF8FF
|
|
888
|
+
// - Non-characters: \uFDD0-\uFDEF
|
|
889
|
+
text = text.replace(/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFE00-\uFE0F\uFEFF\uE000-\uF8FF\uFDD0-\uFDEF]/g, "");
|
|
890
|
+
|
|
867
891
|
// Don't escape pi, Greek, or just a-z0-9 or Unicode Greek, or empty
|
|
868
892
|
if (
|
|
869
893
|
/^\\?[a-zA-Z0-9]+$/.test(text) ||
|
package/lib/mathml2latex.umd.js
CHANGED
|
@@ -281,24 +281,24 @@
|
|
|
281
281
|
bigCommand: {
|
|
282
282
|
decimals: [8721, 8719, 8720, 10753, 10754, 10752, 8899, 8898, 10756, 10758, 8897, 8896, 8747, 8750, 8748, 8749, 10764, 8747],
|
|
283
283
|
scripts: [
|
|
284
|
-
"\\sum",
|
|
285
|
-
"\\prod",
|
|
286
|
-
"\\coprod",
|
|
287
|
-
"\\bigoplus",
|
|
288
|
-
"\\bigotimes",
|
|
289
|
-
"\\bigodot",
|
|
290
|
-
"\\bigcup",
|
|
291
|
-
"\\bigcap",
|
|
292
|
-
"\\biguplus",
|
|
293
|
-
"\\bigsqcup",
|
|
294
|
-
"\\bigvee",
|
|
295
|
-
"\\bigwedge",
|
|
296
|
-
"\\int",
|
|
297
|
-
"\\oint",
|
|
298
|
-
"\\iint",
|
|
299
|
-
"\\iiint",
|
|
300
|
-
"\\iiiint",
|
|
301
|
-
"\\idotsint",
|
|
284
|
+
"\\sum ",
|
|
285
|
+
"\\prod ",
|
|
286
|
+
"\\coprod ",
|
|
287
|
+
"\\bigoplus ",
|
|
288
|
+
"\\bigotimes ",
|
|
289
|
+
"\\bigodot ",
|
|
290
|
+
"\\bigcup ",
|
|
291
|
+
"\\bigcap ",
|
|
292
|
+
"\\biguplus ",
|
|
293
|
+
"\\bigsqcup ",
|
|
294
|
+
"\\bigvee ",
|
|
295
|
+
"\\bigwedge ",
|
|
296
|
+
"\\int ",
|
|
297
|
+
"\\oint ",
|
|
298
|
+
"\\iint ",
|
|
299
|
+
"\\iiint ",
|
|
300
|
+
"\\iiiint ",
|
|
301
|
+
"\\idotsint ",
|
|
302
302
|
]
|
|
303
303
|
},
|
|
304
304
|
|
|
@@ -616,9 +616,10 @@
|
|
|
616
616
|
// Thêm xử lý cho các thẻ MathML khác
|
|
617
617
|
result = result
|
|
618
618
|
.replace(/∞/g, "\\infty") // Vô cực
|
|
619
|
-
.replace(
|
|
620
|
-
|
|
621
|
-
|
|
619
|
+
.replace(/∫/g, " \\int "); // Tích phân
|
|
620
|
+
|
|
621
|
+
// Đảm bảo dấu cách sau các lệnh LaTeX quan trọng để tránh dính biến (vd: \intf -> \int f)
|
|
622
|
+
result = result.replace(/\\(int|sum|prod|cos|sin|tan|cot|lim|log|ln)([a-zA-Z0-9])/g, "\\$1 $2");
|
|
622
623
|
|
|
623
624
|
return result;
|
|
624
625
|
}
|
|
@@ -777,7 +778,8 @@
|
|
|
777
778
|
"|": " \\mid ", // PATCH: set-builder mid
|
|
778
779
|
π: " \\pi ", // PATCH: Greek letter
|
|
779
780
|
};
|
|
780
|
-
|
|
781
|
+
const res = operatorMap[it] || escapeSpecialChars(MathSymbol.parseOperator(it));
|
|
782
|
+
return res;
|
|
781
783
|
}
|
|
782
784
|
// --- END PATCH ---
|
|
783
785
|
|
|
@@ -804,6 +806,20 @@
|
|
|
804
806
|
// Math Number
|
|
805
807
|
function parseElementMn(node) {
|
|
806
808
|
let it = NodeTool.getNodeText(node).trim();
|
|
809
|
+
// Loại bỏ các ký tự điều khiển hoặc khoảng trắng lạ
|
|
810
|
+
it = it.replace(/[\u0000-\u001F\u007F-\u009F\u00A0]/g, "");
|
|
811
|
+
|
|
812
|
+
// Danh sách các hàm toán học mở rộng
|
|
813
|
+
const mathFunctions = ["cos", "sin", "tan", "cot", "arccos", "arcsin", "arctan", "arccot", "log", "ln", "lim", "sinh", "cosh", "tanh", "sec", "csc"];
|
|
814
|
+
|
|
815
|
+
if (mathFunctions.some(fn => it.toLowerCase().includes(fn))) {
|
|
816
|
+
// Tìm hàm khớp chính xác nhất
|
|
817
|
+
for (const fn of mathFunctions) {
|
|
818
|
+
if (it.toLowerCase() === fn) {
|
|
819
|
+
return "\\" + fn + " ";
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
807
823
|
return escapeSpecialChars(it);
|
|
808
824
|
}
|
|
809
825
|
|
|
@@ -816,7 +832,7 @@
|
|
|
816
832
|
|
|
817
833
|
// Math Text
|
|
818
834
|
function parseElementMtext(node) {
|
|
819
|
-
let content = NodeTool.getNodeText(node)
|
|
835
|
+
let content = escapeSpecialChars(NodeTool.getNodeText(node))
|
|
820
836
|
.replace(/\s*=\s*/g, " = ")
|
|
821
837
|
.replace(/\s*\.\s*/g, " \\cdot ")
|
|
822
838
|
.trim();
|
|
@@ -870,6 +886,14 @@
|
|
|
870
886
|
}
|
|
871
887
|
|
|
872
888
|
function escapeSpecialChars(text) {
|
|
889
|
+
// Strip problematic Unicode characters:
|
|
890
|
+
// - Control characters: \u0000-\u0008, \u000B-\u000C, \u000E-\u001F, \u007F-\u009F
|
|
891
|
+
// - Zero-width & Invisible: \u200B-\u200F, \u202A-\u202E, \u2060-\u206F, \uFEFF
|
|
892
|
+
// - Variation Selectors: \uFE00-\uFE0F
|
|
893
|
+
// - Private Use Area (PUA): \uE000-\uF8FF
|
|
894
|
+
// - Non-characters: \uFDD0-\uFDEF
|
|
895
|
+
text = text.replace(/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFE00-\uFE0F\uFEFF\uE000-\uF8FF\uFDD0-\uFDEF]/g, "");
|
|
896
|
+
|
|
873
897
|
// Don't escape pi, Greek, or just a-z0-9 or Unicode Greek, or empty
|
|
874
898
|
if (
|
|
875
899
|
/^\\?[a-zA-Z0-9]+$/.test(text) ||
|