MathML in DOMBlogger
The geeky side of me really likes MathML. It is very pretty as source, and while the presentation IMHO is not as good as what LaTeX produces, it is much better than embedding an image of an equation.
Due to the fact that the output is so sexy but it is cumbersome to type the source, I am attempting to produce a DOMDocument based class that generates the actual XML for a MathML equation. Then I will attempt to write a class that parses LaTeX math equations and generates the MathML. Yes, there are already some tools that do this, most of them require that the web server have a LaTeX install with TeX4ht installed, and LaTeX does the conversion.
While that works very well, a pure PHP solution is good because it allows one to secure their server by not allowing php to execute system commands, and it would not require a LaTeX install. Yes, there are already some like that including a rather neat JavaScript implementation, but AFAIK none of them do it with DOMDocument and as far as JavaScript is concerned, I am a firm believer that if it can be done server side, in most cases it should be done server side.
I have a lot of work to do, this will take awhile. Note that currently MathML support varies by browser. Firefox is excellent, Opera has some problems but does some of it, etc.
Testing MathML with a simple equation
Generated MathML for above equation
<math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <mrow> <msup> <mi>x</mi> <mn>2</mn> </msup> <mo>+</mo> <mrow> <mn>4</mn> <mo></mo> <mi>x</mi> </mrow> <mo>+</mo> <mn>4</mn> </mrow> <mo>=</mo> <mn>0</mn> </mrow> </math>
PHP to generate equation
require_once('mathml.inc.php'); $math = new MathML($mdom); $equate[] = $math->msup($math->mathVar('x'),$math->mathNum(2)); $equate[] = $math->addOp(); $fourex[] = $math->mathNum(4); $fourex[] = $math->mulOp(false); $fourex[] = $math->mathVar('x'); $equate[] = $math->mrow($fourex); $equate[] = $math->addOp(); $equate[] = $math->mathNum(4); $fullEquate[] = $math->mrow($equate); $fullEquate[] = $math->equalOp(); $fullEquate[] = $math->mathNum(0); $final = $math->mrow($fullEquate); $mathNode = $math->mathNode(); $mathNode->appendChild($final);
Testing MathML with slightly more complex equation
Generated MathML for above equation
<math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <mi>x</mi> <mo>=</mo> <mfrac> <mrow> <mrow> <mo>−</mo> <mi>b</mi> </mrow> <mo>±</mo> <msqrt> <mrow> <msup> <mi>b</mi> <mn>2</mn> </msup> <mo>−</mo> <mrow> <mn>4</mn> <mo></mo> <mi>a</mi> <mo></mo> <mi>c</mi> </mrow> </mrow> </msqrt> </mrow> <mrow> <mn>2</mn> <mo></mo> <mi>a</mi> </mrow> </mfrac> </mrow> </math>
PHP to generate equation
require_once('mathml.inc.php'); $math = new MathML($mdom); // lets do radical first $radicandArray[] = $math->msup($math->mathVar('b'),$math->mathNum(2)); $radicandArray[] = $math->subOp(); $radicandTail[] = $math->mathNum(4); $radicandTail[] = $math->mulOp(false); $radicandTail[] = $math->mathVar('a'); $radicandTail[] = $math->mulOp(false); $radicandTail[] = $math->mathVar('c'); $radicandArray[] = $math->mrow($radicandTail); $racicand = $math->mrow($radicandArray); $sqrt = $math->msqrt($racicand); // now numerator $numArrayStart[] = $math->subOp(); $numArrayStart[] = $math->mathVar('b'); $numArray[] = $math->mrow($numArrayStart); $numArray[] = $math->plusMinusOp(); $numArray[] = $sqrt; $numerator = $math->mrow($numArray); // now denominator $denominator = $math->mrow(Array($math->mathNum(2),$math->mulOp(false),$math->mathVar('a'))); // the fraction $fraction = $math->mfrac($numerator,$denominator); // put it all together $final = $math->mrow(Array($math->mathVar('x'),$math->equalOp(),$fraction)); $mathNode = $math->mathNode(); $mathNode->appendChild($final);
Testing MathML with integrals
Generated MathML for above equation
<math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <mrow> <mo>∫</mo> <mrow> <mi>u</mi> <mo></mo> <mrow> <mo>d</mo> <mi>v</mi> </mrow> </mrow> </mrow> <mo>=</mo> <mrow> <mrow> <mi>u</mi> <mo></mo> <mi>v</mi> </mrow> <mo>−</mo> <mrow> <mo>∫</mo> <mrow> <mi>v</mi> <mo></mo> <mrow> <mo>d</mo> <mi>u</mi> </mrow> </mrow> </mrow> </mrow> </mrow> </math>
PHP to generate equation
require_once('mathml.inc.php'); $math = new MathML($mdom); $leftHand[] = $math->integralOp(); $lArg[] = $math->mathVar('u'); $lArg[] = $math->mulOp(false); $lArg[] = $math->mrow(Array($math->diffOp(),$math->mathVar('v'))); $leftHand[] = $math->mrow($lArg); $rightHand[] = $math->mrow(Array($math->mathVar('u'),$math->mulOp(false),$math->mathVar('v'))); $rightHand[] = $math->subOp(); $rightInt[] = $math->integralOp(); $rArg[] = $math->mathVar('v'); $rArg[] = $math->mulOp(false); $rArg[] = $math->mrow(Array($math->diffOp(),$math->mathVar('u'))); $rightInt[] = $math->mrow($rArg); $rightHand[] = $math->mrow($rightInt); $final = $math->mrow(Array($math->mrow($leftHand),$math->equalOp(),$math->mrow($rightHand))); $mathNode = $math->mathNode(); $mathNode->appendChild($final);
The Goal
The goal of this class, when done, is to make the above (and other) equations as easy to generate in DOMBlogger as:
require_once('mathml.inc.php'); $math = new MathML($dom); $mathNode = $math->latex('latexString');
This is going to take awhile, I want it to also work with DOMDocument supplied JS for things like equation expansion or math font size increase w/o needing to zoom entire page, etc. This is my side project I work on when I need a break from other stuff. Eventually I hope it to be quite good yet remain somewhat KISS.
What would be really cool would be a MathML -> SVG ->PNG converter for browsers that do not support MathML. However, I suspect once webkit gets MathML support (allegedly soon) only Opera and IE would be left without support, and there is a solution working solution already for IE.