Skip to content

Commit 61ad3e7

Browse files
authored
Support MathML (mml:*) elements for XHTML rendering (#236)
Closes #172
1 parent 3572bd3 commit 61ad3e7

4 files changed

Lines changed: 146 additions & 0 deletions

File tree

phpdotnet/phd/Package/Generic/XHTML.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,48 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
392392
//phd
393393
'phd:toc' => 'format_phd_toc',
394394

395+
// MathML (namespace http://www.w3.org/1998/Math/MathML)
396+
'mml:math' => 'format_mml_element',
397+
// Token
398+
'mml:mi' => 'format_mml_element',
399+
'mml:mn' => 'format_mml_element',
400+
'mml:mo' => 'format_mml_element',
401+
'mml:mtext' => 'format_mml_element',
402+
'mml:mspace' => 'format_mml_element',
403+
'mml:ms' => 'format_mml_element',
404+
// Layout
405+
'mml:mrow' => 'format_mml_element',
406+
'mml:mfrac' => 'format_mml_element',
407+
'mml:msqrt' => 'format_mml_element',
408+
'mml:mroot' => 'format_mml_element',
409+
'mml:mstyle' => 'format_mml_element',
410+
'mml:merror' => 'format_mml_element',
411+
'mml:mpadded' => 'format_mml_element',
412+
'mml:mphantom' => 'format_mml_element',
413+
'mml:mfenced' => 'format_mml_element',
414+
'mml:menclose' => 'format_mml_element',
415+
// Scripts and limits
416+
'mml:msub' => 'format_mml_element',
417+
'mml:msup' => 'format_mml_element',
418+
'mml:msubsup' => 'format_mml_element',
419+
'mml:munder' => 'format_mml_element',
420+
'mml:mover' => 'format_mml_element',
421+
'mml:munderover' => 'format_mml_element',
422+
'mml:mmultiscripts' => 'format_mml_element',
423+
'mml:mprescripts' => 'format_mml_element',
424+
'mml:none' => 'format_mml_element',
425+
// Tables
426+
'mml:mtable' => 'format_mml_element',
427+
'mml:mtr' => 'format_mml_element',
428+
'mml:mtd' => 'format_mml_element',
429+
'mml:mlabeledtr' => 'format_mml_element',
430+
// Semantics
431+
'mml:semantics' => 'format_mml_element',
432+
'mml:annotation' => 'format_mml_element',
433+
'mml:annotation-xml' => 'format_mml_element',
434+
// Actions
435+
'mml:maction' => 'format_mml_element',
436+
395437
); /* }}} */
396438

397439
private $mytextmap = array(
@@ -631,6 +673,37 @@ function format_phd_toc($open, $name, $attrs, $props) {
631673
) . "</div>\n";
632674
}
633675

676+
/**
677+
* Handle MathML elements (mml:* namespace).
678+
* Strips the "mml:" prefix and outputs the HTML5 local name.
679+
*/
680+
public function format_mml_element($open, $name, $attrs, $props) {
681+
$localName = substr($name, 4);
682+
683+
if ($open) {
684+
$attrStr = '';
685+
686+
// Add xmlns on the <math> root element for XHTML compatibility
687+
if ($localName === 'math') {
688+
$attrStr .= ' xmlns="' . Reader::XMLNS_MATHML . '"';
689+
}
690+
691+
// Preserve MathML attributes (stored under XMLNS_DOCBOOK as they have no namespace)
692+
foreach ($attrs[Reader::XMLNS_DOCBOOK] as $attr => $val) {
693+
$attrStr .= ' ' . $attr . '="' . $this->TEXT($val) . '"';
694+
}
695+
696+
// Preserve xml:id as id
697+
if (isset($attrs[Reader::XMLNS_XML]["id"])) {
698+
$attrStr .= ' id="' . $attrs[Reader::XMLNS_XML]["id"] . '"';
699+
}
700+
701+
return '<' . $localName . $attrStr . ($props["empty"] ? '/>' : '>');
702+
}
703+
704+
return '</' . $localName . '>';
705+
}
706+
634707
public function createLink($for, &$desc = null, $type = Format::SDESC) {
635708
$retval = null;
636709
if (isset($this->indexes[$for])) {

phpdotnet/phd/Reader.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class Reader extends \XMLReader
77
const XMLNS_XLINK = "http://www.w3.org/1999/xlink";
88
const XMLNS_PHD = "http://www.php.net/ns/phd";
99
const XMLNS_DOCBOOK = "http://docbook.org/ns/docbook";
10+
const XMLNS_MATHML = "http://www.w3.org/1998/Math/MathML";
1011

1112
protected OutputHandler $outputHandler;
1213

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<chapter xml:id="mathml_rendering" xmlns="http://docbook.org/ns/docbook" xmlns:mml="http://www.w3.org/1998/Math/MathML">
3+
4+
<section>
5+
<para>1. Inline MathML equation</para>
6+
<para>
7+
The quadratic formula is
8+
<mml:math display="inline"><mml:mi>x</mml:mi><mml:mo>=</mml:mo><mml:mfrac><mml:mrow><mml:mo>-</mml:mo><mml:mi>b</mml:mi><mml:mo>±</mml:mo><mml:msqrt><mml:mrow><mml:msup><mml:mi>b</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mo>-</mml:mo><mml:mn>4</mml:mn><mml:mi>a</mml:mi><mml:mi>c</mml:mi></mml:mrow></mml:msqrt></mml:mrow><mml:mrow><mml:mn>2</mml:mn><mml:mi>a</mml:mi></mml:mrow></mml:mfrac></mml:math>.
9+
</para>
10+
</section>
11+
12+
<section>
13+
<para>2. Self-closing mspace element</para>
14+
<para>
15+
<mml:math><mml:mi>a</mml:mi><mml:mspace width="1em"/><mml:mi>b</mml:mi></mml:math>
16+
</para>
17+
</section>
18+
19+
<section>
20+
<para>3. Element with mathvariant attribute</para>
21+
<para>
22+
<mml:math><mml:mi mathvariant="bold">x</mml:mi></mml:math>
23+
</para>
24+
</section>
25+
26+
</chapter>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
MathML rendering
3+
--FILE--
4+
<?php
5+
namespace phpdotnet\phd;
6+
7+
require_once __DIR__ . "/../../setup.php";
8+
9+
$xmlFile = __DIR__ . "/data/mathml_rendering.xml";
10+
11+
$config->xmlFile = $xmlFile;
12+
13+
$format = new TestPHPChunkedXHTML($config, $outputHandler);
14+
15+
$render = new TestRender(new Reader($outputHandler), $config, $format);
16+
17+
$render->run();
18+
?>
19+
--EXPECT--
20+
Filename: mathml_rendering.html
21+
Content:
22+
<div id="mathml_rendering" class="chapter">
23+
24+
<div class="section">
25+
<p class="para">1. Inline MathML equation</p>
26+
<p class="para">
27+
The quadratic formula is
28+
<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>x</mi><mo>=</mo><mfrac><mrow><mo>-</mo><mi>b</mi><mo>±</mo><msqrt><mrow><msup><mi>b</mi><mn>2</mn></msup><mo>-</mo><mn>4</mn><mi>a</mi><mi>c</mi></mrow></msqrt></mrow><mrow><mn>2</mn><mi>a</mi></mrow></mfrac></math>.
29+
</p>
30+
</div>
31+
32+
<div class="section">
33+
<p class="para">2. Self-closing mspace element</p>
34+
<p class="para">
35+
<math xmlns="http://www.w3.org/1998/Math/MathML"><mi>a</mi><mspace width="1em"/><mi>b</mi></math>
36+
</p>
37+
</div>
38+
39+
<div class="section">
40+
<p class="para">3. Element with mathvariant attribute</p>
41+
<p class="para">
42+
<math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="bold">x</mi></math>
43+
</p>
44+
</div>
45+
46+
</div>

0 commit comments

Comments
 (0)