math-formula-processor.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /**
  2. * 数学公式预处理器
  3. * 用于标准化各种数学公式格式,避免渲染死循环
  4. */
  5. window.MathFormulaProcessor = {
  6. /**
  7. * 预处理数学公式内容
  8. * @param {string} content 原始内容
  9. * @return {string} 处理后的内容
  10. */
  11. processContent: function(content) {
  12. if (!content || typeof content !== 'string') {
  13. return content;
  14. }
  15. // 1. 标准化数学公式分隔符
  16. content = this.standardizeDelimiters(content);
  17. // 2. 转义特殊字符
  18. content = this.escapeSpecialChars(content);
  19. // 3. 修复常见的LaTeX错误
  20. content = this.fixLatexErrors(content);
  21. return content;
  22. },
  23. /**
  24. * 标准化数学公式分隔符
  25. */
  26. standardizeDelimiters: function(content) {
  27. // 统一使用 $ 和 $$ 作为分隔符
  28. content = content.replace(/\\\(\\s*\$/g, '$');
  29. content = content.replace(/\$\\s*\\\)/g, '$');
  30. content = content.replace(/\\\[\\s*\$/g, '$$');
  31. content = content.replace(/\$\\s*\\\]/g, '$$');
  32. return content;
  33. },
  34. /**
  35. * 转义特殊字符,防止渲染冲突
  36. */
  37. escapeSpecialChars: function(content) {
  38. // 检测是否已经在公式中
  39. let inFormula = false;
  40. let result = '';
  41. for (let i = 0; i < content.length; i++) {
  42. const char = content[i];
  43. const nextChar = content[i + 1];
  44. // 检测公式开始
  45. if (char === '$' && nextChar === '$') {
  46. inFormula = true;
  47. result += char;
  48. i++; // 跳过下一个$
  49. continue;
  50. }
  51. if (char === '$') {
  52. inFormula = !inFormula;
  53. result += char;
  54. continue;
  55. }
  56. // 在公式外转义某些字符
  57. if (!inFormula) {
  58. switch (char) {
  59. case '\\':
  60. // 只转义不是LaTeX命令的反斜杠
  61. if (this.isLatexCommand(content, i)) {
  62. result += char;
  63. } else {
  64. result += '\\\\';
  65. }
  66. break;
  67. case '{':
  68. case '}':
  69. result += char;
  70. break;
  71. default:
  72. result += char;
  73. }
  74. } else {
  75. result += char;
  76. }
  77. }
  78. return result;
  79. },
  80. /**
  81. * 检测当前位置是否在LaTeX命令中
  82. */
  83. isLatexCommand: function(content, index) {
  84. // 简单检测:查看反斜杠后面是否跟着字母
  85. let i = index + 1;
  86. while (i < content.length && /\s/.test(content[i])) {
  87. i++;
  88. }
  89. return i < content.length && /[a-zA-Z]/.test(content[i]);
  90. },
  91. /**
  92. * 修复常见的LaTeX错误
  93. */
  94. fixLatexErrors: function(content) {
  95. // 1. 修复不匹配的公式分隔符
  96. let formulaCount = 0;
  97. let inDisplayFormula = false;
  98. for (let i = 0; i < content.length; i++) {
  99. if (content[i] === '$' && content[i + 1] === '$') {
  100. if (inDisplayFormula) {
  101. formulaCount++;
  102. inDisplayFormula = false;
  103. } else {
  104. inDisplayFormula = true;
  105. }
  106. i++; // 跳过下一个$
  107. } else if (content[i] === '$') {
  108. formulaCount++;
  109. }
  110. }
  111. // 如果公式数量是奇数,补全分隔符
  112. if (formulaCount % 2 === 1) {
  113. content += '$';
  114. }
  115. // 2. 修复空的数学公式
  116. content = content.replace(/\$\s*\$/g, ' $\\text{空}$ ');
  117. content = content.replace(/\$\$\s*\$\$/g, '$$\\text{空}$$$');
  118. return content;
  119. },
  120. /**
  121. * 清理重复的数学公式标记
  122. */
  123. cleanupDuplicateMarkers: function(content) {
  124. // 移除连续的相同分隔符
  125. content = content.replace(/\$\$\$\$\$/g, '$$');
  126. content = content.replace(/\$\$\$/g, '$');
  127. return content;
  128. }
  129. };