MathJax或类似的东西:在表达式内渲染任意HTML元素?

时间:2019-11-15 18:52:40

标签: html latex mathjax mathml

我对Web应用程序中的数学表达式呈现有特定的需求,尽管到目前为止,我主要关注MathJax,但我当然不愿意对此有所了解。

我需要的是呈现一种数学表达式的能力,其中一个或多个术语实质上可以是任意HTML框元素,如下所示: Example output

...如果布局响应HTML框的大小(例如,括号会像其他“常规” LaTeX / MathJax元素一样自动调整大小以匹配其高度),那将是更好的选择,但是如果我需要指定一个确切的大小(以像素为单位)或诸如此类,也可以。如果我不得不,甚至可以在实际的可视化效果中插入一个“占位符”元素,但可以确切知道它在输出中的位置,因此我可以将HTML元素精确地覆盖在其顶部。

换句话说,我愿意接受现成的甚至是骇人听闻的解决方案。只是需要一些有效的方法。

也可能相关:我实际上只会使用非常基本的LaTeX元素:括号,分数,普通运算符。如果这是一个复杂的因素,我什至根本不需要能够支持上述示例中的求和。

1 个答案:

答案 0 :(得分:4)

有两种方法可以解决此问题。您建议插入一个占位符并将其覆盖的建议是一种,可以按照以下步骤进行:

<script type="text/x-mathjax-config">
MathJax.Hub.Queue(function () {
  var PX = function (x) {return x.toFixed(2) + 'px'};
  var space = document.getElementById('space');
  var sbox = space.getBoundingClientRect();
  var math = MathJax.Hub.getJaxFor(space).SourceElement().previousSibling;
  var mbox = math.getBoundingClientRect();
  var x = sbox.left - mbox.left;
  var y = sbox.top - mbox.top;
  var html = MathJax.HTML.Element('div', {id:'html', style: {
    position:'absolute', top:PX(y), left:PX(x), 
    width:PX(sbox.width), height:PX(sbox.height), 'line-height':'normal'
  }}, [[
    'table',{style:{height:'100%', width:'100%', background:'red', border:'5px solid green'}}, [[
      'tr',{},[[
        'td',{},['abc']
      ]]
    ]]
  ]]);
  math.style.position = 'relative';
  math.appendChild(html);
});
</script>
<script id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS_CHTML" defer></script>

<div style="xfont-size: 150%">
$$x + \left(\,\cssId{space}{\Space{100px}{55px}{45px}}\,\right) + y$$
</div>

在这里,我们使用\Space插入所需宽度,高度和深度的空白区域,并使用\cssId标记该空间,以便稍后进行检索。我们使用MathJax.Hub.Queue()对要在MathJax对数学进行类型设置后运行的函数进行排队。此函数查找space-holder元素,并找到MathJax用于保存数学的容器元素。它获取每个边界框的信息,并计算相对于数学的叠加层位置。然后,它创建了叠加层(在这种情况下,内容进行了硬编码),并具有适当的大小和部分以覆盖占位符的顶部。

这可以工作,但是有点尴尬,对于显示的方程式,如果窗口大小发生变化,则覆盖层可能不会停留在正确的位置。另外,它仅设置为可用于CommonHTML输出。


以下是一种替代方法,它使用<semantics>元素将HTML包含到MathJax使用的内部MathML结构中。它添加了一个新的宏\insertHTML{}

<script type="text/x-mathjax-config">
MathJax.Hub.Config({
  CommonHTML: {
    styles: {
      //
      // remove CSS for '.mjx-math *'
      //
      '.mjx-math *': {
        display: null,
        '-webkit-box-sizing': null,
        '-moz-box-sizing': null,
        'box-sizing': null,
        'tex-align': null
      },
      //
      // add CSS for .mjx-math span instead
      //
      '.mjx-math span': {
        display: 'inline-block',
        '-webkit-box-sizing': 'context-box !important',
        '-moz-box-sizing': 'context-box !important',
        'box-sizing': 'context-box !important',
        'tex-align': 'left'
      },
      //
      // override display for .mjx-char spans
      //
      'span.mjx-char': {
        display: 'block'
      }
    }
  }
});
MathJax.Hub.Register.StartupHook("TeX Jax Ready", function () {
  var MML = MathJax.ElementJax.mml;
  var TEX = MathJax.InputJax.TeX;
  TEX.Definitions.macros.insertHTML = 'InsertHTML';
  TEX.Parse.Augment({
    InsertHTML: function (name) {
      var html = this.GetArgument(name).replace(/^\s*<!--\s*/,'').replace(/\s*-->\s*$/,'');
      var span = MathJax.HTML.Element('mjx-reset', {style: {display:'inline-block'}});
      span.innerHTML = html;  // serious security risk if users can enter math
      span.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
      var mml = MML["annotation-xml"](MML.xml(span)).With({encoding:"application/xhtml+xml",isToken:true});
      this.Push(MML.semantics(mml));
    }
  });
});
</script>
<script id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS_CHTML" defer></script>

<div style="xfont-size: 150%">
$$x + \left(\,\insertHTML{<!--
<table width="100" height="100"
  style="display:inline-table; vertical-align:-.25em; background:red; border:5px solid green;
  box-sizing:border-box !important">
<tr><td style="text-align:center">abc</td></tr>
</table>
-->}\,\right) + y$$
</div>


$$x+\left(\insertHTML{<!--
<i>this</i> is <b>html</b>
-->}\right)+y$$

由于MathJax不会直接处理包含HTML标记的数学,因此您必须将HTML放入注释中,您可以在上面的两个示例表达式中看到该注释。这个版本适用于所有输出格式(甚至包括MathML输出),但是由于它包含在MathJax布局内部,因此确实需要一些配置来覆盖一些适用于内容的CommonHTML CSS。

在这种情况下,无论窗口发生什么变化,HTML都将保持正确的位置,它的优点是可以在表达式本身中给出HTML。但是请注意,如果您的站点允许用户输入数学,这将带来安全风险,因为这意味着他们可以在您的页面中输入任意HTML。在这种情况下,您需要先清理HTML,然后再在innerHTML函数中设置InsertHTML