From e6a1aed03a919aa98fa6893f5206abc28177453a Mon Sep 17 00:00:00 2001 From: Christian Perfect Date: Fri, 25 Apr 2014 16:47:20 +0100 Subject: [PATCH] copy ctop.js into the content-mathml extension Developed in mathjax/ctop. Uses the MathML jax's DOMfilterHooks to manipulate MathML elements before they're parsed into the internal format. --- unpacked/extensions/MathML/content-mathml.js | 1537 +++++++++++++++++- 1 file changed, 1464 insertions(+), 73 deletions(-) diff --git a/unpacked/extensions/MathML/content-mathml.js b/unpacked/extensions/MathML/content-mathml.js index d06f61eb7..c5ecbb4ad 100644 --- a/unpacked/extensions/MathML/content-mathml.js +++ b/unpacked/extensions/MathML/content-mathml.js @@ -44,87 +44,1478 @@ */ -MathJax.Extension["MathML/content-mathml"] = { - version: "2.3" -}; +MathJax.Extension["MathML/content-mathml"] = (function() { + /* + * Content MathML to Presentation MathML conversion + * + * based on David Carlisle's ctop.js - https://web-xslt.googlecode.com/svn/trunk/ctop/ctop.js + * + */ + + var CToP = { + version: "2.4", + + /* Transform the given elements from Content MathML to Presentation MathML and replace the original elements + */ + transform: function(elements){ + for (var i = 0; i< elements.length;i++){ + var mathNode = CToP.transformElement(elements[i]); + elements[i].parentNode.replaceChild(mathNode,elements[i]); + } + }, + + /* Transform a Content MathML element into Presentation MathML, and return the new element + */ + transformElement: function(element) { + var mathNode = element.cloneNode(false); + for(var j=0;j1){ + CToP.applyTransform(mrow,args[0],tokenPrecedence); + } + CToP.appendToken(mrow,'mo',name); + if(args.length>0){ + var z = args[(args.length==1)?0:1]; + CToP.applyTransform(mrow,z,tokenPrecedence); + } + if(needsBrackets) { + CToP.appendToken(mrow,'mo',')'); + } + parentNode.appendChild(mrow); + } + }, + + /* Transform an infix operator + * + * (function factory) + */ + infix: function(name,tokenPrecedence) { + return function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mrow = CToP.createElement('mrow'); + var needsBrackets = precedence>tokenPrecedence; + if(needsBrackets) { + CToP.appendToken(mrow,'mo','('); + } + for(var j=0;j0) { + CToP.appendToken(mrow,'mo',name); + } + CToP.applyTransform(mrow,args[j],tokenPrecedence); + } + if(needsBrackets) { + CToP.appendToken(mrow,'mo',')'); + } + parentNode.appendChild(mrow); + } + }, + + /* Transform an iterated operation, e.g. summation + * + * (function factory + */ + iteration: function(name,limitSymbol) { + return function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mrow = CToP.createElement('mrow'); + var mo = CToP.createElement('mo'); + mo.textContent = name; + var munderover = CToP.createElement('munderover'); + munderover.appendChild(mo); + var mrow1 = CToP.createElement('mrow'); + for(var i=0; i',1), + "lt": CToP.infix('<',1), + "geq": CToP.infix('\u2265',1), + "leq": CToP.infix('\u2264',1), + "equivalent": CToP.infix('\u2261',1), + "approx": CToP.infix('\u2248',1), + "subset": CToP.infix('\u2286',2), + "prsubset": CToP.infix('\u2282',2), + "cartesianproduct": CToP.infix('\u00D7',2), + "cartesian_product": CToP.infix('\u00D7',2), + "vectorproduct": CToP.infix('\u00D7',2), + "scalarproduct": CToP.infix('.',2), + "outerproduct": CToP.infix('\u2297',2), + "sum": CToP.iteration('\u2211','='), + "product": CToP.iteration('\u220F','='), + "forall": CToP.bind('\u2200',',',','), + "exists": CToP.bind('\u2203','\u007c',','), + "lambda": CToP.bind('\u03BB','.',','), + "limit": CToP.iteration('lim','\u2192'), + "sdev": CToP.fn('\u03c3'), + "determinant": CToP.fn('det'), + "max": CToP.minmax('max'), + "min": CToP.minmax('min'), + "real": CToP.fn('\u211b'), + "imaginary": CToP.fn('\u2111'), + "set": CToP.set('{','}'), + "list": CToP.set('(',')') + } + CToP.applyTokens['exp'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var msup = CToP.createElement('msup'); + CToP.appendToken(msup,'mi','e'); + CToP.applyTransform(msup,args[0],0); + parentNode.appendChild(msup); + } + + CToP.applyTokens['union'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + if(bvars.length) { + CToP.iteration('\u22C3','=')(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence); + } else { + CToP.infix('\u222A',2)(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence); + } + } + CToP.applyTokens['intersect'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + if(bvars.length) { + CToP.iteration('\u22C2','=')(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence); + } else { + CToP.infix('\u2229',2)(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence); + } + } + + CToP.applyTokens['floor'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mrow = CToP.createElement('mrow'); + CToP.appendToken(mrow,'mo','\u230a'); + CToP.applyTransform(mrow,args[0],0); + CToP.appendToken(mrow,'mo','\u230b'); + parentNode.appendChild(mrow); + } + CToP.applyTokens['conjugate'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mover = CToP.createElement('mover'); + CToP.applyTransform(mover,args[0],0); + CToP.appendToken(mover,'mo','\u00af'); + parentNode.appendChild(mover); + } + CToP.applyTokens['abs'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mrow = CToP.createElement('mrow'); + CToP.appendToken(mrow,'mo','|'); + CToP.applyTransform(mrow,args[0],0); + CToP.appendToken(mrow,'mo','|'); + parentNode.appendChild(mrow); + } + CToP.applyTokens['and'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + if(bvars.length || qualifiers.length) { + CToP.iteration('\u22c0','=')(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,4); + } else { + CToP.infix('\u2227',2)(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence); + } + } + CToP.applyTokens['or'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + if(bvars.length || qualifiers.length) { + CToP.iteration('\u22c1','=')(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,4); + } else { + CToP.infix('\u2228',2)(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence); + } + } + CToP.applyTokens['xor'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + if(bvars.length || qualifiers.length) { + CToP.iteration('xor','=')(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,4); + } else { + CToP.infix('xor',2)(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence); + } + } + CToP.applyTokens['card'] = CToP.applyTokens['size'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mrow = CToP.createElement('mrow'); + CToP.appendToken(mrow,'mo','|'); + CToP.applyTransform(mrow,args[0],0); + CToP.appendToken(mrow,'mo','|'); + parentNode.appendChild(mrow); + } + CToP.applyTokens['mean'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + if(args.length==1) { + var mover = CToP.createElement('mover'); + CToP.applyTransform(mover,args[0],0); + CToP.appendToken(mover,'mo','\u00af'); + parentNode.appendChild(mover); + } else { + parentNode.appendChild(CToP.mfenced(args,'\u27e8','\u27e9')); + } + } + CToP.applyTokens['moment'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var degree,momentabout; + + for(var i=0; i1) { + argrow.appendChild(CToP.mfenced(args,'(',')')); + } else { + CToP.applyTransform(argrow,args[0],0); + } + if(degree) { + var msup = CToP.createElement('msup'); + msup.appendChild(argrow); + var children = CToP.children(degree); + for(var j=0;j3; + if(needsBrackets) { + CToP.appendToken(mrow,'mo','('); + } + for(var j=0;j0) { + CToP.appendToken(mrow,'mo',(args[j].localName=='cn') ? "\u00D7" :"\u2062"); + } + CToP.applyTransform(mrow,args[j],3); + } + if(needsBrackets) { + CToP.appendToken(mrow,'mo',')'); + } + parentNode.appendChild(mrow); + } + + CToP.applyTokens["plus"] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mrow = CToP.createElement('mrow'); + var needsBrackets = precedence>2; + if(needsBrackets) { + CToP.appendToken(mrow,'mo','('); + } + for(var j=0;j0) { + var n; + if(arg.localName=='cn' && !(children.length) && (n=Number(arg.textContent)) <0) { + CToP.appendToken(mrow,'mo','\u2212'); + CToP.appendToken(mrow,'mn', -n); + } else if(arg.localName=='apply' && children.length==2 && children[0].localName=='minus') { + CToP.appendToken(mrow,'mo','\u2212'); + CToP.applyTransform(mrow,children[1],2); + } else if(arg.localName=='apply' && children.length>2 && children[0].localName=='times' && children[1].localName=='cn' && ( n=Number(children[1].textContent) < 0)) { + CToP.appendToken(mrow,'mo','\u2212'); + children[1].textContent=-n;// fix me: modifying document + CToP.applyTransform(mrow,arg,2); + } else{ + CToP.appendToken(mrow,'mo','+'); + CToP.applyTransform(mrow,arg,2); + } + } else { + CToP.applyTransform(mrow,arg,2); + } + } + if(needsBrackets) { + CToP.appendToken(mrow,'mo',')'); + } + parentNode.appendChild(mrow); + } + + CToP.applyTokens['transpose'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var msup = CToP.createElement('msup'); + CToP.applyTransform(msup,args[0],precedence); + CToP.appendToken(msup,'mi','T'); + parentNode.appendChild(msup); + } + + CToP.applyTokens['power'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var msup = CToP.createElement('msup'); + CToP.applyTransform(msup,args[0],3); + CToP.applyTransform(msup,args[1],precedence); + parentNode.appendChild(msup); + } + + CToP.applyTokens['selector'] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var msub = CToP.createElement('msub'); + var mrow = args ? args[0]: CToP.createElement('mrow'); + CToP.applyTransform(msub,mrow,0); + var mrow2 = CToP.createElement('mrow'); + for(var i=1;i1){ + CToP.applyTransform(mrow,args[1],0); + } + } + CToP.appendToken(mrow,'mo','\u230B'); + parentNode.appendChild(mrow); + } + + CToP.applyTokens["factorial"] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mrow = CToP.createElement('mrow'); + CToP.applyTransform(mrow,args[0],4); + CToP.appendToken(mrow,'mo','!'); + parentNode.appendChild(mrow); + } + + CToP.applyTokens["root"] = function(parentNode,contentMMLNode,firstArg,args,bvars,qualifiers,precedence) { + var mr; + if(firstArg.localName=='root' && (qualifiers.length==0 || (qualifiers[0].localName=='degree' && qualifiers[0].textContent=='2'))){ + mr = CToP.createElement('msqrt'); + for(var i=0;i1) { + var msup = CToP.createElement('msup'); + CToP.applyTransform(msup,bvar,0); + CToP.appendToken(msup,'mn',degree); + mrow.appendChild(msup); + } else { + CToP.applyTransform(mrow,bvar,0); + } + } + for(var i=0;i0){ + if(hadFirst){ + CToP.appendToken(mrow,'mo','+'); + } + CToP.appendToken(mrow,'mn',degree); + } + } + msup.appendChild(mrow); + mrow = CToP.createElement('mrow'); + mrow.appendChild(msup); + if(args.length){ + CToP.applyTransform(mrow,args[0],0); + } + m.appendChild(mrow); + mrow = CToP.createElement('mrow'); + for(var i=0;i but use MATHML.Parse's preProcessMath to apply the normal preprocessing. - if (!MATHML.ParseXML) {MATHML.ParseXML = MATHML.createParser()} - var doc = MATHML.ParseXML(PARSE.preProcessMath(data.math)); - - // Now transform the using the ctop stylesheet. - var newdoc = MATHML.ctopXSLT.transformToDocument(doc); - - if ((typeof newdoc) === "string") { - // Internet Explorer returns a string, so just use it. - data.math = newdoc; - } else if (window.XMLSerializer) { - // Serialize the again. We could directly provide the DOM content - // but other prefilterHooks may assume data.math is still a string. - var serializer = new XMLSerializer(); - data.math = serializer.serializeToString(newdoc.documentElement, doc); - } + MATHML.DOMfilterHooks.Add(function (data) { + data.math = CToP.transformElement(data.math); }); - /* - * The following is taken from ctop.xsl and mml3mml2.xsl - * (https://web-xslt.googlecode.com/svn/trunk/ctop/) - * which is Copyright (c) David Carlisle 2001, 2002, 2008, 2009, 2013. - * It is used by permission of David Carlisle, who has agreed to allow it to - * be released under the Apache2 licesnse. - */ - var ctopStylesheet = ' +i+i//eieiE0x.(-1)λ.|iddomaincodomainimageunexpected domainofapplicationrestriction{  if    otherwise/!/maxmin(+)()mod(×)gcdxor¬..,||¯arglcm=><|dddddD,++,divdiv()gradgrad()curl2()||×=limlimtendsto()eloglog,σσ2medianmode()[|][|]()()[m,|m,=;]()det||T,.ZRQNCPeiNaNtruefalseπγ()()||,share)(][}{)(][}{\)(}{><top right;color:;background-color:; 0 decimalpoint decimalpoint.decimalpoint*0.1em0.15em0.2em0.15em 0/\)(:=)'; - /* - * End of ctop.xsl amd mml3mml2.csl material. - */ - - var ctop; - if (window.XSLTProcessor) { - // standard method: just use an XSLTProcessor and parse the stylesheet - if (!MATHML.ParseXML) {MATHML.ParseXML = MATHML.createParser()} - MATHML.ctopXSLT = new XSLTProcessor(); - MATHML.ctopXSLT.importStylesheet(MATHML.ParseXML(ctopStylesheet)); - } else if (MathJax.Hub.Browser.isMSIE) { - // nonstandard methods for Internet Explorer - if (MathJax.Hub.Browser.versionAtLeast("9.0")) { - // For Internet Explorer >= 9, use createProcessor - ctop = new ActiveXObject("Msxml2.FreeThreadedDOMDocument"); - ctop.loadXML(ctopStylesheet); - var xslt = new ActiveXObject("Msxml2.XSLTemplate"); - xslt.stylesheet = ctop; - MATHML.ctopXSLT = { - ctop: xslt.createProcessor(), - transformToDocument: function(doc) { - this.ctop.input = doc; - this.ctop.transform(); - return this.ctop.output; - } - } - } else { - // For Internet Explorer <= 8, use transformNode - ctop = MATHML.createMSParser(); - ctop.async = false; - ctop.loadXML(ctopStylesheet); - MATHML.ctopXSLT = { - ctop: ctop, - transformToDocument: function(doc) { - return doc.documentElement.transformNode(this.ctop); - } - } - } - } else { - // No XSLT support. Do not change the content. - MATHML.ctopXSLT = null; - } - MathJax.Hub.Startup.signal.Post("MathML content-mathml Ready"); });