JAVASCRIPT   56

mml2jax js

Guest on 2nd August 2022 03:55:45 PM

  1. /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
  2. /* vim: set ts=2 et sw=2 tw=80: */
  3.  
  4. /*************************************************************
  5.  *
  6.  *  MathJax/extensions/mml2jax.js
  7.  *  
  8.  *  Implements the MathML to Jax preprocessor that locates <math> nodes
  9.  *  within the text of a document and replaces them with SCRIPT tags
  10.  *  for processing by MathJax.
  11.  *
  12.  *  ---------------------------------------------------------------------
  13.  *  
  14.  *  Copyright (c)  The MathJax Consortium
  15.  *
  16.  *  Licensed under the Apache License, Version 2.0 (the "License");
  17.  *  you may not use this file except in compliance with the License.
  18.  *  You may obtain a copy of the License at
  19.  *
  20.  *      http://www.apache.org/licenses/LICENSE-2.0
  21.  *
  22.  *  Unless required by applicable law or agreed to in writing, software
  23.  *  distributed under the License is distributed on an "AS IS" BASIS,
  24.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25.  *  See the License for the specific language governing permissions and
  26.  *  limitations under the License.
  27.  */
  28.  
  29. MathJax.Extension.mml2jax = {
  30.   version: "2.6.0",
  31.   config: {
  32.     preview: "mathml"       // Use the <math> element as the
  33.                             //   preview.  Set to "none" for no preview,
  34.                             //   set to "alttext" to use the alttext attribute
  35.                             //   of the <math> element, set to "altimg" to use
  36.                             //   an image described by the altimg* attributes
  37.                             //   or set to an array specifying an HTML snippet
  38.                             //   to use a fixed preview for all math
  39.  
  40.   },
  41.   MMLnamespace: "http://www.w3.org/1998/Math/MathML",
  42.  
  43.   PreProcess: function (element) {
  44.     if (!this.configured) {
  45.       this.config = MathJax.Hub.CombineConfig("mml2jax",this.config);
  46.       if (this.config.Augment) {MathJax.Hub.Insert(this,this.config.Augment)}
  47.       this.InitBrowser();
  48.       this.configured = true;
  49.     }
  50.     if (typeof(element) === "string") {element = document.getElementById(element)}
  51.     if (!element) {element = document.body}
  52.     var mathArray = [];
  53.     //
  54.     //  Handle all math tags with no namespaces
  55.     //
  56.     this.PushMathElements(mathArray,element,"math");
  57.     //
  58.     //  Handle math with namespaces in XHTML
  59.     //
  60.     this.PushMathElements(mathArray,element,"math",this.MMLnamespace);
  61.     //
  62.     //  Handle math with namespaces in HTML
  63.     //
  64.     var i, m;
  65.     if (typeof(document.namespaces) !== "undefined") {
  66.       //
  67.       // IE namespaces are listed in document.namespaces
  68.       //
  69.       try {
  70.         for (i = 0, m = document.namespaces.length; i < m; i++) {
  71.           var ns = document.namespaces[i];
  72.           if (ns.urn === this.MMLnamespace)
  73.             {this.PushMathElements(mathArray,element,ns.name+":math")}
  74.         }
  75.       } catch (err) {}
  76.     } else {
  77.       //
  78.       //  Everybody else
  79.       //  
  80.       var html = document.getElementsByTagName("html")[0];
  81.       if (html) {
  82.         for (i = 0, m = html.attributes.length; i < m; i++) {
  83.           var attr = html.attributes[i];
  84.           if (attr.nodeName.substr(0,6) === "xmlns:" && attr.nodeValue === this.MMLnamespace)
  85.             {this.PushMathElements(mathArray,element,attr.nodeName.substr(6)+":math")}
  86.         }
  87.       }
  88.     }
  89.     this.ProcessMathArray(mathArray);
  90.   },
  91.  
  92.   PushMathElements: function (array,element,name,namespace) {
  93.     var math, preview = MathJax.Hub.config.preRemoveClass;
  94.     if (namespace) {
  95.       if (!element.getElementsByTagNameNS) return;
  96.       math = element.getElementsByTagNameNS(namespace,name);
  97.     } else {
  98.       math = element.getElementsByTagName(name);
  99.     }
  100.     for (var i = 0, m = math.length; i < m; i++) {
  101.       var parent = math[i].parentNode;
  102.       if (parent && parent.className !== preview &&
  103.          !parent.isMathJax && !math[i].prefix === !namespace) array.push(math[i]);
  104.     }
  105.   },
  106.  
  107.   ProcessMathArray: function (math) {
  108.     var i, m = math.length;
  109.     if (m) {
  110.       if (this.MathTagBug) {
  111.         for (i = 0; i < m; i++) {
  112.           if (math[i].nodeName === "MATH") {this.ProcessMathFlattened(math[i])}
  113.                                       else {this.ProcessMath(math[i])}
  114.         }
  115.       } else {
  116.         for (i = 0; i < m; i++) {this.ProcessMath(math[i])}
  117.       }
  118.     }
  119.   },
  120.  
  121.   ProcessMath: function (math) {
  122.     var parent = math.parentNode;
  123.     if (!parent || parent.className === MathJax.Hub.config.preRemoveClass) return;
  124.     var script = document.createElement("script");
  125.     script.type = "math/mml";
  126.     parent.insertBefore(script,math);
  127.     if (this.AttributeBug) {
  128.       var html = this.OuterHTML(math);
  129.       if (this.CleanupHTML) {
  130.         html = html.replace(/<\?import .*?>/i,"").replace(/<\?xml:namespace .*?\/>/i,"");
  131.         html = html.replace(/&nbsp;/g,"&#xA0;");
  132.       }
  133.       MathJax.HTML.setScript(script,html); parent.removeChild(math);
  134.     } else {
  135.       var span = MathJax.HTML.Element("span"); span.appendChild(math);
  136.       MathJax.HTML.setScript(script,span.innerHTML);
  137.     }
  138.     if (this.config.preview !== "none") {this.createPreview(math,script)}
  139.   },
  140.  
  141.   ProcessMathFlattened: function (math) {
  142.     var parent = math.parentNode;
  143.     if (!parent || parent.className === MathJax.Hub.config.preRemoveClass) return;
  144.     var script = document.createElement("script");
  145.     script.type = "math/mml";
  146.     parent.insertBefore(script,math);
  147.     var mml = "", node, MATH = math;
  148.     while (math && math.nodeName !== "/MATH") {
  149.       node = math; math = math.nextSibling;
  150.       mml += this.NodeHTML(node);
  151.       node.parentNode.removeChild(node);
  152.     }
  153.     if (math && math.nodeName === "/MATH") {math.parentNode.removeChild(math)}
  154.     script.text = mml + "</math>";
  155.     if (this.config.preview !== "none") {this.createPreview(MATH,script)}
  156.   },
  157.  
  158.   NodeHTML: function (node) {
  159.     var html, i, m;
  160.     if (node.nodeName === "#text") {
  161.       html = this.quoteHTML(node.nodeValue);
  162.     } else if (node.nodeName === "#comment") {
  163.       html = "<!--" + node.nodeValue + "-->"
  164.     } else {
  165.       // In IE, outerHTML doesn't properly quote attributes, so quote them by hand
  166.       // In Opera, HTML special characters aren't quoted in attributes, so quote them
  167.       html = "<"+node.nodeName.toLowerCase();
  168.       for (i = 0, m = node.attributes.length; i < m; i++) {
  169.         var attribute = node.attributes[i];
  170.         if (attribute.specified && attribute.nodeName.substr(0,10) !== "_moz-math-") {
  171.           // Opera 11.5 beta turns xmlns into xmlns:xmlns, so put it back (*** check after 11.5 is out ***)
  172.           html += " "+attribute.nodeName.toLowerCase().replace(/xmlns:xmlns/,"xmlns")+"=";
  173.           var value = attribute.nodeValue; // IE < 8 doesn't properly set style by setAttributes
  174.           if (value == null && attribute.nodeName === "style" && node.style) {value = node.style.cssText}
  175.           html += '"'+this.quoteHTML(value)+'"';
  176.         }
  177.       }
  178.       html += ">";
  179.       // Handle internal HTML (possibly due to <semantics> annotation or missing </math>)
  180.       if (node.outerHTML != null && node.outerHTML.match(/(.<\/[A-Z]+>|\/>)$/)) {
  181.         for (i = 0, m = node.childNodes.length; i < m; i++)
  182.           {html += this.OuterHTML(node.childNodes[i])}
  183.         html += "</"+node.nodeName.toLowerCase()+">";
  184.       }
  185.     }
  186.     return html;
  187.   },
  188.   OuterHTML: function (node) {
  189.     if (node.nodeName.charAt(0) === "#") {return this.NodeHTML(node)}
  190.     if (!this.AttributeBug) {return node.outerHTML}
  191.     var html = this.NodeHTML(node);
  192.     for (var i = 0, m = node.childNodes.length; i < m; i++)
  193.       {html += this.OuterHTML(node.childNodes[i]);}
  194.     html += "</"+node.nodeName.toLowerCase()+">";
  195.     return html;
  196.   },
  197.   quoteHTML: function (string) {
  198.     if (string == null) {string = ""}
  199.     return string.replace(/&/g,"&#x26;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;");
  200.   },
  201.  
  202.   createPreview: function (math,script) {
  203.     var preview = this.config.preview;
  204.     if (preview === "none") return;
  205.     var isNodePreview = false;
  206.     if (preview === "mathml") {
  207.       isNodePreview = true;
  208.       // mathml preview does not work with IE < 9, so fallback to alttext.
  209.       if (this.MathTagBug) {preview = "alttext"} else {preview = math.cloneNode(true)}
  210.     }
  211.     if (preview === "alttext" || preview === "altimg") {
  212.       isNodePreview = true;
  213.       var alttext = this.filterPreview(math.getAttribute("alttext"));
  214.       if (preview === "alttext") {
  215.         if (alttext != null) {preview = MathJax.HTML.TextNode(alttext)} else {preview = null}
  216.       } else {
  217.         var src = math.getAttribute("altimg");
  218.         if (src != null) {
  219.           // FIXME: use altimg-valign when display="inline"?
  220.           var style = {width: math.getAttribute("altimg-width"), height: math.getAttribute("altimg-height")};
  221.           preview = MathJax.HTML.Element("img",{src:src,alt:alttext,style:style});
  222.         } else {preview = null}
  223.       }
  224.     }
  225.     if (preview) {
  226.       var span;
  227.       if (isNodePreview) {
  228.         span = MathJax.HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass});
  229.         span.appendChild(preview);
  230.       } else {
  231.         span = MathJax.HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass},preview);
  232.       }
  233.       script.parentNode.insertBefore(span,script);
  234.     }
  235.   },
  236.  
  237.   filterPreview: function (text) {return text},
  238.  
  239.   InitBrowser: function () {
  240.     var test = MathJax.HTML.Element("span",{id:"<", className: "mathjax", innerHTML: "<math><mi>x</mi><mspace /></math>"});
  241.     var html = test.outerHTML || "";
  242.     this.AttributeBug = html !== "" && !(
  243.       html.match(/id="&lt;"/) &&           // "<" should convert to "&lt;"
  244.       html.match(/class="mathjax"/) &&     // IE leaves out quotes
  245.       html.match(/<\/math>/)               // Opera 9 drops tags after self-closing tags
  246.     );
  247.     this.MathTagBug = test.childNodes.length > 1;    // IE < 9 flattens unknown tags
  248.     this.CleanupHTML = MathJax.Hub.Browser.isMSIE;   // remove namespace and other added tags
  249.   }
  250.  
  251. };
  252.  
  253. //
  254. // We register the preprocessors with the following priorities:
  255. // - mml2jax.js: 5
  256. // - jsMath2jax.js: 8
  257. // - asciimath2jax.js, tex2jax.js: 10 (default)
  258. // See issues 18 and 484 and the other *2jax.js files.
  259. //
  260. MathJax.Hub.Register.PreProcessor(["PreProcess",MathJax.Extension.mml2jax],5);
  261. MathJax.Ajax.loadComplete("[MathJax]/extensions/mml2jax.js");

Raw Paste


Login or Register to edit or fork this paste. It's free.