HTML-仅适用于 MathML 的回退

HTML-only fallback for MathML

MathML 是一种编写数学的网络标准,可以轻松缩放而无需像素化(就像 SVG)、复制和粘贴以及屏幕阅读器阅读。

Chrome 拒绝在 JavaScript polyfill 存在的基础上实现它。 (I kid you not.) Edge's support is 'Not currently planned'. Thus, it's just Safari and Firefox (and some EPub readers) 支持 MathML。

鉴于实现如此参差不齐,后备内容是 100% 必要的。通常的解决方案是MathJax;但这不适用于 JavaScript 禁用或更可能损坏的用户。

我们生活在一个 HTML 很容易允许没有 JavaScript 的后备内容的时代(参见 <picture><audio><video> 标签)。有什么方法可以为 MathML 做到这一点吗?

据我所知,没有HTML唯一的方法来检测对 MathML 的支持。

但是,一种 SVG 方式。

<switch> SVG 元素呈现其自身的第一个直接子元素,其中该子元素的某些布尔属性缺失或计算结果为真。其中一个属性是 requiredExtensions 属性,它要求用户代理必须支持特定的扩展以呈现指定的元素。

因此,如果您有一个 SVG <foreignObject> 元素(用于在 SVG 中嵌入非 SVG 元素)并设置了 requiredExtensions="http://www.w3.org/1998/Math/MathML",并且 <foreignObject> 放在 <switch> 元素中,如果支持 MathML,将呈现 <math> 元素,如果不支持 MathML,将呈现下一个元素。

因此,对于一个基本的 MathML 示例:<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn><mo>+</mo><mn>1</mn><mo>=</mo><mn>2</mn></math> 是 1 + 1 = 2 的 MathML。

一个基本的 SVG 回退是 <svg xmlns="http://www.w3.org/2000/svg" width="65" height="23"><text y="15" font-size="16">1 + 1 = 2</text></svg>(更复杂的回退可以用 Mathjax-Node 生成)。

所以完整的带有回退的 MathML 表达式将是:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="120" height="40">
  <switch>
    <foreignObject requiredExtensions="http://www.w3.org/1998/Math/MathML" width="120" height="40">
      <math xmlns="http://www.w3.org/1998/Math/MathML">
        <mn>1</mn><mo>+</mo><mn>1</mn><mo>=</mo><mn>2</mn><mtext>MathML</mtext>
      </math>
    </foreignObject>
    <text y="15" font-size="16">1 + 1 = 2 (SVG)</text>
  </switch>
</svg>

我已经在 Firefox(呈现 MathML)、Edge、IE11 和 Chrome(呈现 SVG)中测试了以上内容。我没有测试 Safari,因为我没有 Mac.

编辑:Safari 9 呈现 MathML。

但是我要支持IE8!

为什么?

因为!

很好。

如果您想保留复制 + 数学的能力,则不能使用 <picture> 标签来嵌入您的 SVG/MathML 混合体 - 请改用 <object>

(我在这里使用的是 DataUrl,但您可以轻松地将 SVG 保存为外部文件):

<object typemustmatch type="image/svg+xml" data="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjQwIj4NCiAgPHN3aXRjaD4NCiAgICA8Zm9yZWlnbk9iamVjdCByZXF1aXJlZEV4dGVuc2lvbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTgvTWF0aC9NYXRoTUwiIHdpZHRoPSIxMjAiIGhlaWdodD0iNDAiPg0KICAgICAgPG1hdGggeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTgvTWF0aC9NYXRoTUwiPg0KICAgICAgICA8bW4+MTwvbW4+PG1vPis8L21vPjxtbj4xPC9tbj48bW8+PTwvbW8+PG1uPjI8L21uPjxtdGV4dD5NYXRoTUw8L210ZXh0Pg0KICAgICAgPC9tYXRoPg0KICAgIDwvZm9yZWlnbk9iamVjdD4NCiAgICA8dGV4dCB5PSIxNSIgZm9udC1zaXplPSIxNiI+MSArIDEgPSAyIChTVkcpPC90ZXh0Pg0KICA8L3N3aXRjaD4NCjwvc3ZnPg==">
  1 + 1 = 2 (You don't support SVG)
</object>

(您可以使用 CloudConvert 或类似方法将 SVG 渲染为 PNG,如果您 真的 想要,则将其放入对象中。)

好了。一点预渲染,你有一个不需要 JavaScript 或 CSS 的 MathML 后备 - 只需要 HTML.

编辑:我制作了一个 NPM 包来自动创建 MathML、SVG 和 PNG。可以查到here.

我在第一次回答时并没有意识到这一点,但是您 可以 实际上使用 <object> 标签直接显示 MathML - MIME 类型MathML 是 application/mathml+xml.

所以你可以有一个 <object> 标签指向一个 mml 文件,里面有你想要的任何回退内容(我建议你的方程式的 SVG 表示,可能在它自己的 <object> 用于 PNG 回退)。

我已经测试并确认这在 Firefox(显示 MathML)、Edge、Internet Explorer 11 和 Chrome(显示 SVG)中有效。

编辑:Safari 显示 SVG,而不是 MathML。 (即使它支持 MathML。)