/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /************************************************************* * * MathJax/extensions/mml2jax.js * * Implements the MathML to Jax preprocessor that locates nodes * within the text of a document and replaces them with SCRIPT tags * for processing by MathJax. * * --------------------------------------------------------------------- * * Copyright (c) 2010-2015 The MathJax Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ MathJax.Extension.mml2jax = { version: "2.5.0", config: { preview: "mathml" // Use the element as the // preview. Set to "none" for no preview, // set to "alttext" to use the alttext attribute // of the element, set to "altimg" to use // an image described by the altimg* attributes // or set to an array specifying an HTML snippet // to use a fixed preview for all math }, MMLnamespace: "http://www.w3.org/1998/Math/MathML", PreProcess: function (element) { if (!this.configured) { this.config = MathJax.Hub.CombineConfig("mml2jax",this.config); if (this.config.Augment) {MathJax.Hub.Insert(this,this.config.Augment)} this.InitBrowser(); this.configured = true; } if (typeof(element) === "string") {element = document.getElementById(element)} if (!element) {element = document.body} var mathArray = []; // // Handle all math tags with no namespaces // this.PushMathElements(mathArray,element,"math"); // // Handle math with namespaces in XHTML // this.PushMathElements(mathArray,element,"math",this.MMLnamespace); // // Handle math with namespaces in HTML // var i, m; if (typeof(document.namespaces) !== "undefined") { // // IE namespaces are listed in document.namespaces // try { for (i = 0, m = document.namespaces.length; i < m; i++) { var ns = document.namespaces[i]; if (ns.urn === this.MMLnamespace) {this.PushMathElements(mathArray,element,ns.name+":math")} } } catch (err) {} } else { // // Everybody else // var html = document.getElementsByTagName("html")[0]; if (html) { for (i = 0, m = html.attributes.length; i < m; i++) { var attr = html.attributes[i]; if (attr.nodeName.substr(0,6) === "xmlns:" && attr.nodeValue === this.MMLnamespace) {this.PushMathElements(mathArray,element,attr.nodeName.substr(6)+":math")} } } } this.ProcessMathArray(mathArray); }, PushMathElements: function (array,element,name,namespace) { var math, preview = MathJax.Hub.config.preRemoveClass; if (namespace) { if (!element.getElementsByTagNameNS) return; math = element.getElementsByTagNameNS(namespace,name); } else { math = element.getElementsByTagName(name); } for (var i = 0, m = math.length; i < m; i++) { var parent = math[i].parentNode; if (parent && parent.className !== preview && !math[i].prefix === !namespace) {array.push(math[i])} } }, ProcessMathArray: function (math) { var i, m = math.length; if (m) { if (this.MathTagBug) { for (i = 0; i < m; i++) { if (math[i].nodeName === "MATH") {this.ProcessMathFlattened(math[i])} else {this.ProcessMath(math[i])} } } else { for (i = 0; i < m; i++) {this.ProcessMath(math[i])} } } }, ProcessMath: function (math) { var parent = math.parentNode; if (!parent || parent.className === MathJax.Hub.config.preRemoveClass) return; var script = document.createElement("script"); script.type = "math/mml"; parent.insertBefore(script,math); if (this.AttributeBug) { var html = this.OuterHTML(math); if (this.CleanupHTML) { html = html.replace(/<\?import .*?>/i,"").replace(/<\?xml:namespace .*?\/>/i,""); html = html.replace(/ /g," "); } MathJax.HTML.setScript(script,html); parent.removeChild(math); } else { var span = MathJax.HTML.Element("span"); span.appendChild(math); MathJax.HTML.setScript(script,span.innerHTML); } if (this.config.preview !== "none") {this.createPreview(math,script)} }, ProcessMathFlattened: function (math) { var parent = math.parentNode; if (!parent || parent.className === MathJax.Hub.config.preRemoveClass) return; var script = document.createElement("script"); script.type = "math/mml"; parent.insertBefore(script,math); var mml = "", node, MATH = math; while (math && math.nodeName !== "/MATH") { node = math; math = math.nextSibling; mml += this.NodeHTML(node); node.parentNode.removeChild(node); } if (math && math.nodeName === "/MATH") {math.parentNode.removeChild(math)} script.text = mml + ""; if (this.config.preview !== "none") {this.createPreview(MATH,script)} }, NodeHTML: function (node) { var html, i, m; if (node.nodeName === "#text") { html = this.quoteHTML(node.nodeValue); } else if (node.nodeName === "#comment") { html = "" } else { // In IE, outerHTML doesn't properly quote attributes, so quote them by hand // In Opera, HTML special characters aren't quoted in attributes, so quote them html = "<"+node.nodeName.toLowerCase(); for (i = 0, m = node.attributes.length; i < m; i++) { var attribute = node.attributes[i]; if (attribute.specified && attribute.nodeName.substr(0,10) !== "_moz-math-") { // Opera 11.5 beta turns xmlns into xmlns:xmlns, so put it back (*** check after 11.5 is out ***) html += " "+attribute.nodeName.toLowerCase().replace(/xmlns:xmlns/,"xmlns")+"="; var value = attribute.nodeValue; // IE < 8 doesn't properly set style by setAttributes if (value == null && attribute.nodeName === "style" && node.style) {value = node.style.cssText} html += '"'+this.quoteHTML(value)+'"'; } } html += ">"; // Handle internal HTML (possibly due to annotation or missing ) if (node.outerHTML != null && node.outerHTML.match(/(.<\/[A-Z]+>|\/>)$/)) { for (i = 0, m = node.childNodes.length; i < m; i++) {html += this.OuterHTML(node.childNodes[i])} html += ""; } } return html; }, OuterHTML: function (node) { if (node.nodeName.charAt(0) === "#") {return this.NodeHTML(node)} if (!this.AttributeBug) {return node.outerHTML} var html = this.NodeHTML(node); for (var i = 0, m = node.childNodes.length; i < m; i++) {html += this.OuterHTML(node.childNodes[i]);} html += ""; return html; }, quoteHTML: function (string) { if (string == null) {string = ""} return string.replace(/&/g,"&").replace(//g,">").replace(/\"/g,"""); }, createPreview: function (math,script) { var preview = this.config.preview; if (preview === "none") return; var isNodePreview = false; if (preview === "mathml") { isNodePreview = true; // mathml preview does not work with IE < 9, so fallback to alttext. if (this.MathTagBug) {preview = "alttext"} else {preview = math.cloneNode(true)} } if (preview === "alttext" || preview === "altimg") { isNodePreview = true; var alttext = this.filterPreview(math.getAttribute("alttext")); if (preview === "alttext") { if (alttext != null) {preview = MathJax.HTML.TextNode(alttext)} else {preview = null} } else { var src = math.getAttribute("altimg"); if (src != null) { // FIXME: use altimg-valign when display="inline"? var style = {width: math.getAttribute("altimg-width"), height: math.getAttribute("altimg-height")}; preview = MathJax.HTML.Element("img",{src:src,alt:alttext,style:style}); } else {preview = null} } } if (preview) { var span; if (isNodePreview) { span = MathJax.HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass}); span.appendChild(preview); } else { span = MathJax.HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass},preview); } script.parentNode.insertBefore(span,script); } }, filterPreview: function (text) {return text}, InitBrowser: function () { var test = MathJax.HTML.Element("span",{id:"<", className: "mathjax", innerHTML: "x"}); var html = test.outerHTML || ""; this.AttributeBug = html !== "" && !( html.match(/id="<"/) && // "<" should convert to "<" html.match(/class="mathjax"/) && // IE leaves out quotes html.match(/<\/math>/) // Opera 9 drops tags after self-closing tags ); this.MathTagBug = test.childNodes.length > 1; // IE < 9 flattens unknown tags this.CleanupHTML = MathJax.Hub.Browser.isMSIE; // remove namespace and other added tags } }; // // We register the preprocessors with the following priorities: // - mml2jax.js: 5 // - jsMath2jax.js: 8 // - asciimath2jax.js, tex2jax.js: 10 (default) // See issues 18 and 484 and the other *2jax.js files. // MathJax.Hub.Register.PreProcessor(["PreProcess",MathJax.Extension.mml2jax],5); MathJax.Ajax.loadComplete("[MathJax]/extensions/mml2jax.js");