mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-10-31 02:27:01 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			262 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* -*- 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-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.6.0",
 | |
|   config: {
 | |
|     preview: "mathml"       // Use the <math> element as the
 | |
|                             //   preview.  Set to "none" for no preview,
 | |
|                             //   set to "alttext" to use the alttext attribute
 | |
|                             //   of the <math> 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 &&
 | |
|          !parent.isMathJax && !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 + "</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 && 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 <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;
 | |
|     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: "<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
 | |
|   }
 | |
| 
 | |
| };
 | |
| 
 | |
| //
 | |
| // 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");
 |