123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /* -*- 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 <math> nodes
- * within the text of a document and replaces them with SCRIPT tags
- * for processing by MathJax.
- *
- * ---------------------------------------------------------------------
- *
- * Copyright (c) 2010-2013 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.2",
- config: {
- preview: "alttext" // Use the <math> element's alttext as the
- // preview. Set to "none" for no preview,
- // 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}
- //
- // Handle all math tags with no namespaces
- //
- this.ProcessMathArray(element.getElementsByTagName("math"));
- //
- // Handle math with namespaces in XHTML
- //
- if (element.getElementsByTagNameNS)
- {this.ProcessMathArray(element.getElementsByTagNameNS(this.MMLnamespace,"math"))}
- //
- // 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.ProcessMathArray(element.getElementsByTagName(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.ProcessMathArray(element.getElementsByTagName(attr.nodeName.substr(6)+":math"))}
- }
- }
- }
- },
-
- ProcessMathArray: function (math) {
- var i;
- if (math.length) {
- if (this.MathTagBug) {
- for (i = math.length-1; i >= 0; i--) {
- if (math[i].nodeName === "MATH") {this.ProcessMathFlattened(math[i])}
- else {this.ProcessMath(math[i])}
- }
- } else {
- for (i = math.length-1; i >= 0; i--) {this.ProcessMath(math[i])}
- }
- }
- },
-
- ProcessMath: function (math) {
- var parent = math.parentNode;
- 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;
- 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 + "</math>";
- 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 = "<!--" + node.nodeValue + "-->"
- } 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) {
- // 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 <semantics> annotation or missing </math>)
- 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 += "</"+node.nodeName.toLowerCase()+">";
- }
- }
- 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 += "</"+node.nodeName.toLowerCase()+">";
- return html;
- },
- quoteHTML: function (string) {
- if (string == null) {string = ""}
- return string.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\"/g,""");
- },
-
- createPreview: function (math,script) {
- var preview = this.config.preview;
- if (preview === "none") return;
- if (preview === "alttext") {
- var text = math.getAttribute("alttext");
- if (text != null) {preview = [this.filterPreview(text)]} else {preview = null}
- }
- if (preview) {
- preview = MathJax.HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass},preview);
- script.parentNode.insertBefore(preview,script);
- }
- },
-
- filterPreview: function (text) {return text},
-
- InitBrowser: function () {
- var test = MathJax.HTML.Element("span",{id:"<", className: "mathjax", innerHTML: "<math><mi>x</mi><mspace /></math>"});
- 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
- }
- };
- MathJax.Hub.Register.PreProcessor(["PreProcess",MathJax.Extension.mml2jax]);
- MathJax.Ajax.loadComplete("[MathJax]/extensions/mml2jax.js");
|