tex-mml-svg.js渲染化学公式化学反应式(对不能渲染的化学公式进行强制兼容)

html 复制代码
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script>
      window.MathJax = {
        tex: {
          packages: { '[+]': ['mhchem'] },
        },
      }
    </script>
    <!-- <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-svg.js"></script> -->
    <script src="./public/tex-mml-svg.js"></script>
  </head>
  <body>
    <div id="preview"></div>
    <div id="preview2"></div>
    <script></script>
    <script>
      const cleanChemLatex = (tex, type) => {
        console.log('Original LaTeX:', tex)

        // 1. 移除 \[ 和 \] 标记(因为我们通过 display 参数控制)
        tex = tex
          .replace(/^\s*\\?\[/, '')
          .replace(/\\?\]\s*$/, '')
          .trim()

        // 2. 清理可能的双倍反斜杠(需要在字符串中处理)
        tex = tex.replace(/\\\\/g, '\\')

        // 3. 修复 \chemabove 和 \chembelow 的空第一个参数问题

        if (type === '1') {
          tex = tex.replace(/\\chemabove/g, '')
          tex = tex.replace(/\\chembelow/g, '-')
        } else {
          tex = tex.replace(/\\chemabove/g, '')
          tex = tex.replace(/\\chembelow/g, '')
        }
        tex = tex.replace(/\\ce/g, '')

        // 4. 修复 \phantom{} 空内容
        tex = tex.replace(/\\phantom\{\}/g, '\\phantom{X}')

        // 5. 修复 \phantom{|} 问题
        tex = tex.replace(/\\phantom\{\|\}/g, '\\phantom{X}')

        // 6. 检查并移除多余的右花括号
        let depth = 0
        let cleaned = ''
        let skipNext = false

        for (let i = 0; i < tex.length; i++) {
          if (skipNext) {
            skipNext = false
            continue
          }

          const char = tex[i]
          const nextChar = tex[i + 1]

          // 跳过转义字符
          if (char === '\\') {
            cleaned += char
            if (nextChar) {
              cleaned += nextChar
              i++
            }
            continue
          }

          if (char === '{') {
            depth++
            cleaned += char
          } else if (char === '}') {
            // 只添加右括号如果有匹配的左括号
            if (depth > 0) {
              depth--
              cleaned += char
            } else {
              // 跳过多余的右括号
              console.log('Skipping extra closing brace at position', i)
            }
          } else {
            cleaned += char
          }
        }

        // 7. 如果还有未闭合的左括号,添加对应的右括号
        while (depth > 0) {
          cleaned += '}'
          depth--
        }

        // 8. 移除连续的空格和换行
        cleaned = cleaned.replace(/\s+/g, ' ').trim()

        console.log('Cleaned LaTeX:', cleaned)
        return cleaned
      }

      try {
        async function renderTexToSVG(tex, display = false) {
          await MathJax.startup.promise

          const node = await MathJax.tex2svgPromise(tex, { display })

          return node
        }

        const preview = document.getElementById('preview')

        let tex =
          '\n\n\\[\\ce{\\chembelow{I}{\\phantom{}}} \\chemabove{}{\\displaystyle\\overset{\\displaystyle OCH3}{\\phantom{|}}} \\chembelow{}{\\phantom{}}} + \\chembelow{}{\\displaystyle\\overset{\\displaystyle O}{||}} \\chemabove{Ph}{\\phantom{}}}C-CH=CH-Ph ->[\\text{Ni(acac)2, (S)-DTBM-Segphos}][\\text{Mn powder, Ball Milling (30 Hz, 8 h)}] \\chembelow{}{\\displaystyle\\overset{\\displaystyle O}{||}} \\chemabove{Ph}{\\phantom{}}}C-CH( \\chembelow{}{\\displaystyle\\overset{\\displaystyle OCH3}{\\phantom{|}}} \\chemabove{}{\\phantom{}}} )-CH2-Ph\\]\n\n'

        tex = cleanChemLatex(tex, '2')

        renderTexToSVG(tex, true).then((node) => {
          preview.innerHTML = ''
          preview.appendChild(node)
        })
      } catch (error) {
        console.error('Error rendering TeX to SVG:', error)
      }

      try {
        async function renderTexToSVG(tex, display = false) {
          await MathJax.startup.promise

          const node = await MathJax.tex2svgPromise(tex, { display })

          return node
        }

        const preview = document.getElementById('preview2')

        let tex =
          '\n\n\\[\\ce{Ar^{1}-X + \\chemabove{R}{\\phantom{}} \\chembelow{}{\\displaystyle\\overset{\\displaystyle O}{||}} -CH=CH-Ar^{2} ->[\\text{Ni cat. / L*, Ball Milling}][\\text{Additive}] \\chemabove{R}{\\phantom{}} \\chembelow{}{\\displaystyle\\overset{\\displaystyle O}{||}} -CH(Ar^{1})-CH2-Ar^{2}}\\]\n\n'

        tex = cleanChemLatex(tex, '1')

        renderTexToSVG(tex, true).then((node) => {
          preview.innerHTML = ''
          preview.appendChild(node)
        })
      } catch (error) {
        console.error('Error rendering TeX to SVG:', error)
      }
    </script>
  </body>
</html>
相关推荐
da-peng-song1 天前
ArcGIS Desktop使用入门(四)——生成经纬度坐标
arcgis·经纬度坐标
da-peng-song1 天前
ArcGIS Desktop使用入门(三)图层右键工具——定义查询
数据库·arcgis·拆分数据·定义查询
星座5281 天前
破解水环境空间分析难题,迈向智慧水环境管理:ArcGIS水质评价、污染预测与洪水监测核心技术揭秘
arcgis·水环境·水文
非科班Java出身GISer2 天前
ArcGIS JS 基础教程(10):Camera 相机控制
arcgis·arcgis js 相机·arcgis js 相机控制·arcgis js 视角控制·arcgis js 飞行定位·arcgis js 定位·arcgis js 各种定位
码语智行3 天前
Shapefile获取空间数据和中心点坐标
java·arcgis
码语智行3 天前
地图上图、空间拓扑查询示例
java·arcgis
DXM05213 天前
第10期| 卷积神经网络CNN通俗详解:AI遥感的底层核心
人工智能·python·神经网络·机器学习·arcgis·cnn·文心一言
智航GIS4 天前
ArcGIS大师之路500技---078补零
arcgis
DXM05215 天前
第8期| 传统机器学习遥感解译:SVM & 随机森林分类全流程实操
人工智能·python·随机森林·机器学习·支持向量机·arcgis·自然语言处理
非科班Java出身GISer5 天前
ArcGIS JS 基础教程(9):天空盒与大气效果
arcgis·arcgis js 天空盒·arcgis js 大气效果·arcgis js 大气层·arcgis 场景背景