jenkins-bot has submitted this change and it was merged.
Change subject: New rendering option LaTeXML
......................................................................
New rendering option LaTeXML
Introduces a new rending option to render TeX to MathML
via LaTeXML.
Bug: 43222
Change-Id: I5d29e219c0d3b907e22ea0bb3b30f000d8a7a9f8
---
M Math.hooks.php
M Math.i18n.php
M Math.php
A MathLaTeXML.php
M MathRenderer.php
M README
M db/math.sql
M tests/MathDatabaseTest.php
A tests/MathLaTeXMLTest.php
M tests/MathRendererTest.php
10 files changed, 552 insertions(+), 38 deletions(-)
Approvals:
MaxSem: Verified; Looks good to me, approved
jenkins-bot: Verified
diff --git a/Math.hooks.php b/Math.hooks.php
index a1d9fea..3489da5 100644
--- a/Math.hooks.php
+++ b/Math.hooks.php
@@ -81,7 +81,7 @@
* @return array of strings
*/
private static function getMathNames() {
- global $wgUseMathJax;
+ global $wgUseMathJax, $wgUseLaTeXML;
$names = array(
MW_MATH_PNG => wfMessage( 'mw_math_png' )->escaped(),
MW_MATH_SOURCE => wfMessage( 'mw_math_source'
)->escaped(),
@@ -89,7 +89,9 @@
if ( $wgUseMathJax ) {
$names[MW_MATH_MATHJAX] = wfMessage( 'mw_math_mathjax'
)->escaped();
}
-
+ if ( $wgUseLaTeXML ) {
+ $names[MW_MATH_LATEXML] = wfMessage( 'mw_math_latexml'
)->escaped();
+ }
return $names;
}
diff --git a/Math.i18n.php b/Math.i18n.php
index 1b42f56..9f5fd34 100644
--- a/Math.i18n.php
+++ b/Math.i18n.php
@@ -22,6 +22,7 @@
'mw_math_png' => 'Always render PNG',
'mw_math_source' => 'Leave it as TeX (for text browsers)',
'mw_math_mathjax' => 'MathJax (experimental; best for most browsers)',
+ 'mw_math_latexml' => 'LaTeXML (experimental; uses MathML)',
// Math errors
'math_failure' => 'Failed to parse',
@@ -34,6 +35,10 @@
'math_bad_output' => 'Cannot write to or create math output directory',
'math_notexvc' => 'Missing texvc executable; please see math/README to
configure.',
'math_output_error' => 'Cannot store math image on filesystem.',
+ 'math_latexml_timeout' => 'LaTeXML Timeout from \'$1\'',
+ 'math_latexml_invalidresponse' => 'LaTeXML Invalid response from server
\'$1\':',
+ 'math_latexml_invalidxml' => 'LaTeXML MathML is invalid XML.',
+ 'math_latexml_invalidjson' => 'LaTeXML Server response is invalid
JSON.',
);
/** Message documentation (Message documentation)
@@ -41,6 +46,7 @@
* @author Kizito
* @author Shirayuki
* @author Siebrand
+ * @author Physikerwelt
*/
$messages['qqq'] = array(
'math-desc' =>
'{{desc|name=Math|url=http://www.mediawiki.org/wiki/Extension:Math}}',
@@ -53,19 +59,28 @@
See also:
* {{msg-mw|Mw math source}}
-* {{msg-mw|Mw math mathjax}}',
+* {{msg-mw|Mw math mathjax}}
+* {{msg-mw|Mw math latexml}}',
'mw_math_source' => 'In user preferences (math). All mw_math_* messages
MUST be different, things will break otherwise!
-Used as label for radio button.
+Used as label for source radio button.
See also:
* {{msg-mw|Mw math png}}
+* {{msg-mw|Mw math mathjax}}
+* {{msg-mw|Mw math latexml}}',
+ 'mw_math_mathjax' => 'Used as label for mathjax radio button.
+
+See also:
+* {{msg-mw|Mw math png}}
+* {{msg-mw|Mw math source}}
+* {{msg-mw|Mw math latexml}}',
+ 'mw_math_latexml' => 'Used as label for latexml radio button.
+
+See also:
+* {{msg-mw|Mw math png}}
+* {{msg-mw|Mw math source}}
* {{msg-mw|Mw math mathjax}}',
- 'mw_math_mathjax' => 'Used as label for radio button.
-
-See also:
-* {{msg-mw|Mw math png}}
-* {{msg-mw|Mw math source}}',
'math_failure' => 'Used as error message.
This message is followed by "(", Error message(*1), Additional message, "): "
and Source code.
@@ -79,7 +94,12 @@
* {{msg-mw|Math bad tmpdir}}
* {{msg-mw|Math bad output}}
* {{msg-mw|Math notexvc}}
-* {{msg-mw|Math output error}}',
+* {{msg-mw|Math output error}}
+* {{msg-mw|Math latexml timeout}}
+* {{msg-mw|Math latexml noresponse}}
+* {{msg-mw|Math latexml invalidxml}}
+* {{msg-mw|Math latexml invalidjson}}
+',
'math_unknown_error' => 'Used as error message for unknown texvc error.
This message follows the message {{msg-mw|Math failure}}.
@@ -113,6 +133,18 @@
'math_output_error' => 'Used as error message if the texvc output file
could not be stored.
This message follows the message {{msg-mw|Math failure}}.',
+ 'math_latexml_timeout' => 'Used as error message.
+
+This message follows the message {{msg-mw|Math failure}}. ',
+ 'math_latexml_invalidresponse' => 'Used as error message.
+
+This message follows the message {{msg-mw|Math failure}}. ',
+ 'math_latexml_invalidxml' => 'Used as error message.
+
+This message follows the message {{msg-mw|Math failure}}. ',
+ 'math_latexml_invalidjson' => 'Used as error message.
+
+This message follows the message {{msg-mw|Math failure}}. ',
);
/** Achinese (Acèh)
diff --git a/Math.php b/Math.php
index 83bd58a..9314cb7 100644
--- a/Math.php
+++ b/Math.php
@@ -22,7 +22,7 @@
$wgExtensionCredits['parserhook'][] = array(
'path' => __FILE__,
'name' => 'Math',
- 'version' => '1.0',
+ 'version' => '1.1',
'author' => array( 'Tomasz Wegrzanowski', 'Brion Vibber', '...' ),
'descriptionmsg' => 'math-desc',
'url' => 'https://www.mediawiki.org/wiki/Extension:Math',
@@ -38,6 +38,7 @@
define( 'MW_MATH_MODERN', 4 ); /// @deprecated
define( 'MW_MATH_MATHML', 5 ); /// @deprecated
define( 'MW_MATH_MATHJAX', 6 ); /// new in 1.19/1.20
+define( 'MW_MATH_LATEXML', 7 ); /// new in 1.22
/**@}*/
/** For back-compat */
@@ -101,6 +102,32 @@
*/
$wgUseMathJax = false;
+/**
+ * Use of LaTeXML for details see
+ * <http://latexml.mathweb.org/help>
+ *
+ * If you want or need to run your own server, follow these installation
+ * instructions and override $wgLaTeXMLUrl:
+ * <https://svn.mathweb.org/repos/LaTeXML/branches/arXMLiv/INSTALL>
+ *
+ * If you expect heavy load you can specify multiple servers. In that case one
+ * server is randomly chosen for each rendering process. Specify the list of
+ * servers in an array e.g $wgLaTeXMLUrl = array (
'http://latexml.example.com/convert',
+ * 'http://latexml2.example.com/convert');
+ */
+$wgLaTeXMLUrl = 'http://latexml.mathweb.org/convert';
+
+/**
+ * Allows to use LaTeXML as renderer for mathematical equation.
+ */
+$wgUseLaTeXML = false;
+
+/**
+ * The timeout for the HTTP-Request sent to the LaTeXML to render an equation,
+ * in seconds.
+ */
+$wgLaTeXMLTimeout = 240;
+
////////// end of config settings.
$wgDefaultUserOptions['math'] = MW_MATH_PNG;
@@ -119,6 +146,7 @@
$wgAutoloadClasses['MathTexvc'] = $dir . 'MathTexvc.php';
$wgAutoloadClasses['MathSource'] = $dir . 'MathSource.php';
$wgAutoloadClasses['MathMathJax'] = $dir . 'MathMathJax.php';
+$wgAutoloadClasses['MathLaTeXML'] = $dir . 'MathLaTeXML.php';
$wgExtensionMessagesFiles['Math'] = $dir . 'Math.i18n.php';
$wgParserTestFiles[] = $dir . 'mathParserTests.txt';
diff --git a/MathLaTeXML.php b/MathLaTeXML.php
new file mode 100644
index 0000000..ee38317
--- /dev/null
+++ b/MathLaTeXML.php
@@ -0,0 +1,247 @@
+<?php
+/**
+ * MediaWiki math extension
+ *
+ * (c)2012 Moritz Schubotz
+ * GPLv2 license; info in main package.
+ *
+ * Contains the driver function for the LaTeXML daemon
+ * @file
+ */
+
+class MathLaTeXML extends MathRenderer {
+
+ /**
+ * @var String settings for LaTeXML daemon
+ */
+ private $LaTeXMLSettings = '';
+ const DEFAULT_LATEXML_SETTING =
'format=xhtml&whatsin=math&whatsout=math&pmml&cmml&nodefaultresources&preload=LaTeX.pool&preload=article.cls&preload=amsmath.sty&preload=amsthm.sty&preload=amstext.sty&preload=amssymb.sty&preload=eucal.sty&preload=[dvipsnames]xcolor.sty&preload=url.sty&preload=hyperref.sty&preload=[ids]latexml.sty&preload=texvc';
+
+ /**
+ * Gets the settings for the LaTeXML daemon.
+ *
+ * @return string
+ */
+ public function getLaTeXMLSettings() {
+ if ( $this->LaTeXMLSettings ) {
+ return $this->LaTeXMLSettings;
+ } else {
+ return self::DEFAULT_LATEXML_SETTING;
+ }
+ }
+
+ /**
+ * Sets the settings for the LaTeXML daemon.
+ * The settings affect only the current instance of the class.
+ * For a list of possible settings see:
+ * http://dlmf.nist.gov/LaTeXML/manual/commands/latexmlpost.xhtml
+ * An empty value indicates to use the default settings.
+ * @param string $settings
+ */
+ public function setLaTeXMLSettings( $settings ) {
+ $this->LaTeXMLSettings = $settings;
+ }
+
+ /* (non-PHPdoc)
+ * @see MathRenderer::render()
+ */
+ public function render( $forceReRendering = false ) {
+ if ( $forceReRendering ) {
+ $this->setPurge( true );
+ }
+ if ( $this->renderingRequired() ) {
+ $res = $this->doRender( );
+ if ( ! $res ) {
+ return $this->getLastError();
+ }
+ }
+ return $this->getMathMLTag();
+ }
+
+ /**
+ * Helper function to checks if the math tag must be rendered.
+ * @return boolean
+ */
+ private function renderingRequired() {
+ if ( $this->isPurge() ) {
+ wfDebugLog( "Math", "Rerendering was requested." );
+ return true;
+ } else {
+ $dbres = $this->readFromDatabase();
+ if ( $dbres ) {
+ if ( self::isValidMathML( $this->getMathml() )
) {
+ wfDebugLog( "Math", "Valid entry found
in database." );
+ return false;
+ } else {
+ wfDebugLog( "Math", "Malformatted entry
found in database" );
+ return true;
+ }
+ } else {
+ wfDebugLog( "Math", "No entry found in
database." );
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Performs a HTTP Post request to the given host.
+ * Uses $wgLaTeXMLTimeout as timeout.
+ * Generates error messages on failure
+ * @see Http::post()
+ *
+ * @param string $host
+ * @param string $post the encoded post request
+ * @param mixed $res the result
+ * @param mixed $error the formatted error message or null
+ * @param String $httpRequestClass class name of MWHttpRequest (needed
for testing only)
+ * @return boolean success
+ */
+ public function makeRequest( $host, $post, &$res, &$error = '',
$httpRequestClass = 'MWHttpRequest' ) {
+ global $wgLaTeXMLTimeout;
+ $error = '';
+ $res = null;
+ $options = array( 'method' => 'POST', 'postData' => $post,
'timeout' => $wgLaTeXMLTimeout );
+ $req = $httpRequestClass::factory( $host, $options );
+ $status = $req->execute();
+ if ( $status->isGood() ) {
+ $res = $req->getContent();
+ return true;
+ } else {
+ if ( $status->hasMessage( 'http-timed-out' ) ) {
+ $error = $this->getError(
'math_latexml_timeout', $host );
+ $res = false;
+ wfDebugLog( "Math", "\nLaTeXML Timeout:"
+ . var_export( array( 'post' => $post,
'host' => $host
+ , 'wgLaTeXMLTimeout' =>
$wgLaTeXMLTimeout ), true ) . "\n\n" );
+ } else {
+ // for any other unkonwn http error
+ $errormsg = $status->getHtml();
+ $error = $this->getError(
'math_latexml_invalidresponse', $host, $errormsg );
+ wfDebugLog( "Math", "\nLaTeXML NoResponse:"
+ . var_export( array( 'post' => $post,
'host' => $host
+ , 'errormsg' => $errormsg ),
true ) . "\n\n" );
+ }
+ return false;
+ }
+ }
+
+ /* (non-PHPdoc)
+ * @see MathRenderer::writeCache()
+ */
+ public function writeCache() {
+ if ( $this->isChanged() ) {
+ $this->writeToDatabase();
+ }
+ }
+
+ /**
+ * Picks a LaTeXML daemon.
+ * If more than one demon are availible one is chosen from the
+ * $wgLaTeXMLUrl array.
+ * @return string
+ */
+ private static function pickHost() {
+ global $wgLaTeXMLUrl;
+ if ( is_array( $wgLaTeXMLUrl ) ) {
+ $host = array_rand( $wgLaTeXMLUrl );
+ } else {
+ $host = $wgLaTeXMLUrl;
+ }
+ wfDebugLog( "Math", "picking host " . $host );
+ return $host;
+ }
+
+ /**
+ * Does the actual web request to convert TeX to MathML.
+ * @return boolean
+ */
+ private function doRender( ) {
+ $host = self::pickHost();
+ $texcmd = urlencode( $this->tex );
+ $post = $this->getLaTeXMLSettings();
+ $post .= '&tex=' . $texcmd;
+ $this->lastError = '';
+ if ( $this->makeRequest( $host, $post, $res, $this->lastError )
) {
+ $result = json_decode( $res );
+ if ( json_last_error() === JSON_ERROR_NONE ) {
+ if ( self::isValidMathML( $result->result ) ) {
+ $this->setMathml( $result->result );
+ return true;
+ } else {
+ // Do not print bad mathml. It's
probably too verbose and might
+ // mess up the browser output.
+ $this->lastError = $this->getError(
'math_latexml_invalidxml', $host );
+ wfDebugLog( "Math", "\nLaTeXML
InvalidMathML:"
+ . var_export( array( 'post' =>
$post, 'host' => $host
+ , 'result' => $result
), true ) . "\n\n" );
+ return false;
+ }
+ } else {
+ $this->lastError = $this->getError(
'math_latexml_invalidjson', $host );
+ wfDebugLog( "Math", "\nLaTeXML
InvalidJSON:"
+ . var_export( array( 'post' =>
$post, 'host' => $host
+ , 'res' => $res ), true
) . "\n\n" );
+ return false;
+ }
+ } else {
+ // Error message has already been set.
+ return false;
+ }
+ }
+
+ /**
+ * Checks if the input is valid MathML,
+ * and if the root element has the name math
+ * @param string $XML
+ * @return boolean
+ */
+ static public function isValidMathML( $XML ) {
+ $out = false;
+ $prevInternalErrors = libxml_use_internal_errors( true );
+ $xmlObject = simplexml_load_string( $XML );
+ if ( !$xmlObject ) {
+ wfDebugLog( "Math", "XML validation error:\n " .
var_export( $XML, true ) . "\n" );
+ foreach ( libxml_get_errors() as $error ) {
+ wfDebugLog( "Math", "\t" . $error->message );
+ }
+ libxml_clear_errors();
+ } else {
+ $name = $xmlObject->getName();
+ if ( $name == "math" or $name == "table" or $name ==
"div" ) {
+ $out = true;
+ } else {
+ wfDebugLog( "Math", "got wrong root element " .
$name );
+ }
+ }
+ libxml_use_internal_errors( $prevInternalErrors );
+ return $out;
+ }
+
+ /**
+ * Internal version of @link self::embedMathML
+ * @return string
+ * @return html element with rendered math
+ */
+ private function getMathMLTag() {
+ return self::embedMathML( $this->getMathml(), urldecode(
$this->getTex() ) );
+ }
+
+ /**
+ * Embeds the MathML-XML element in a HTML span element with class tex
+ * @param string $mml: the MathML string
+ * @param string $tagId: optional tagID for references like
(pagename#equation2)
+ * @return html element with rendered math
+ */
+ public static function embedMathML( $mml, $tagId = '', $attribs = false
) {
+ $mml = str_replace( "\n", " ", $mml );
+ if ( ! $attribs ) {
+ $attribs = array( 'class' => 'tex', 'dir' => 'ltr' );
+ if ( $tagId ) {
+ $attribs['id'] = $tagId;
+ }
+ $attribs = Sanitizer::validateTagAttributes( $attribs,
'span' );
+ }
+ return Xml::tags( 'span', $attribs, $mml );
+ }
+
+}
\ No newline at end of file
diff --git a/MathRenderer.php b/MathRenderer.php
index 868a4dd..b2fc50c 100644
--- a/MathRenderer.php
+++ b/MathRenderer.php
@@ -9,8 +9,8 @@
*/
/**
- * Abstract base class with static methods for rendering the <math> tags using
- * different technologies. These static methods create a new instance of the
+ * Abstract base class with static methods for rendering the <math> tags using
+ * different technologies. These static methods create a new instance of the
* extending classes and render the math tags based on the mode setting of the
user.
* Furthermore this class handles the caching of the rendered output and
provides
* debug information,
@@ -25,19 +25,24 @@
* The following variables should made private, as soon it can be
verified
* that they are not being directly accessed by other extensions.
*/
- var $mode = MW_MATH_PNG;
- var $tex = '';
+ protected $mode = MW_MATH_PNG;
+ protected $tex = '';
/**
* is calculated by texvc.
* @var string
*/
- var $hash = '';
- var $html = '';
- var $mathml = '';
- var $conservativeness = 0;
- var $params = '';
- var $changed = false;
+ protected $hash = '';
+ protected $html = '';
+ protected $mathml = '';
+ protected $conservativeness = 0;
+ protected $params = '';
+ protected $changed = false;
+ /**
+ * @var boolean forces rerendering if set to true
+ */
+ protected $purge = false;
protected $recall;
+ protected $lastError = '';
/**
* Constructs a base MathRenderer
@@ -45,7 +50,7 @@
* @param string $tex (optional) LaTeX markup
* @param array $params (optional) HTML attributes
*/
- public function __construct( $tex='', $params = array() ) {
+ public function __construct( $tex = '', $params = array() ) {
$this->tex = $tex;
$this->params = $params;
}
@@ -73,7 +78,7 @@
*/
public static function getRenderer( $tex, $params = array(), $mode =
MW_MATH_PNG ) {
global $wgDefaultUserOptions;
- $validModes = array( MW_MATH_PNG, MW_MATH_SOURCE,
MW_MATH_MATHJAX );
+ $validModes = array( MW_MATH_PNG, MW_MATH_SOURCE,
MW_MATH_MATHJAX, MW_MATH_LATEXML );
if ( !in_array( $mode, $validModes ) )
$mode = $wgDefaultUserOptions['math'];
switch ( $mode ) {
@@ -83,11 +88,14 @@
case MW_MATH_MATHJAX:
$renderer = new MathMathJax( $tex, $params );
break;
+ case MW_MATH_LATEXML:
+ $renderer = new MathLaTeXML( $tex, $params );
+ break;
case MW_MATH_PNG:
default:
$renderer = new MathTexvc( $tex, $params );
}
- wfDebugLog ( "Math", 'start rendering $' . $renderer->tex . '$'
);
+ wfDebugLog ( "Math", 'start rendering $' . $renderer->tex . '$
in mode ' . $mode );
return $renderer;
}
@@ -152,9 +160,11 @@
$this->hash = $xhash['md5'];
$this->conservativeness =
$rpage->math_html_conservativeness;
$this->html = $rpage->math_html;
- $this->mathml = $rpage->math_mathml;
- $this->recall = true;
- return true;
+ $this->mathml = utf8_decode( $rpage->math_mathml);
+ if ( StringUtils::isUtf8( $this->mathml ) ) {
+ $this->recall = true;
+ return true;
+ }
}
# Missing from the database and/or the render cache
@@ -189,7 +199,7 @@
'math_outputhash' => $outmd5_sql ,
'math_html_conservativeness' =>
$this->conservativeness,
'math_html' => $this->html,
- 'math_mathml' => $this->mathml,
+ 'math_mathml' => utf8_encode(
$this->mathml ),
),
__METHOD__
);
@@ -210,6 +220,8 @@
$attribs = Sanitizer::mergeAttributes( $attribs, $overrides );
return $attribs;
}
+
+
/**
* Writes cache. Does nothing by default
*/
@@ -255,7 +267,7 @@
/**
* Get the hash calculated by texvc
- *
+ *
* @return string hash
*/
public function getHash() {
@@ -321,7 +333,7 @@
/**
* Get the attributes of the math tag
- *
+ *
* @return array()
*/
public function getParams() {
@@ -332,11 +344,11 @@
* @param array() $params
*/
public function setParams( $params ) {
- //$changed is not set to true here, because the attributes do
not affect
- //the rendering in the current implementation.
- //If this behavior will change in the future $this->tex is no
longer a
- //primary key and the input hash cannot be calculate form
$this->tex
- //only. See the discussion 'Tag extensions in Block mode' on
wikitech-l.
+ // $changed is not set to true here, because the attributes do
not affect
+ // the rendering in the current implementation.
+ // If this behavior will change in the future $this->tex is no
longer a
+ // primary key and the input hash cannot be calculate form
$this->tex
+ // only. See the discussion 'Tag extensions in Block mode' on
wikitech-l.
$this->params = $params;
}
@@ -349,5 +361,32 @@
return $this->changed;
}
+ /**
+ * Checks if there is an explicit user request to rerender the math-tag.
+ * @return boolean
+ */
+ function isPurge( ) {
+ if ( $this->purge ) {
+ return true;
+ }
+ // TODO: Figure out if ?action=purge
+ // until this issue is resolved we use ?mathpurge=true instead
+ global $wgRequest;
+ return ( $wgRequest->getVal( 'mathpurge' ) === "true" );
+ }
+
+ /**
+ * Sets purge. If set to true the render is forced to rerender and must
not
+ * use a cached version.
+ * @return boolean
+ */
+ function setPurge( $purge = true ) {
+ $this->changed = true;
+ $this->purge = $purge;
+ }
+
+ function getLastError(){
+ return $this->lastError;
+ }
}
diff --git a/README b/README
index 8846d84..f003860 100644
--- a/README
+++ b/README
@@ -7,6 +7,16 @@
See the README in the math subdirectory for more info on setting up the
low-level conversion tools.
+MathML support:
+If you prefer MathML rather than images you can use LaTeXML to convert the
+math tags to MathML. To use that feature you have to enable LaTeXML by setting
+$wgUseLaTeXML = true;
+It is possible to choose LaTeXML as default option (for anonymous user) by
setting
+$wgDefaultUserOptions['math'] = MW_MATH_LATEXML;
+in the LocalSettings.php file.
+The LaTeXML option requires php5-curl to be installed. Without php5-curl no
proper
+error handling can be guaranteed.
+
MathJax configuration:
Client-side configuration of MathJax can be done by specifying a mathJax.config
table, which takes a table as described in:
diff --git a/db/math.sql b/db/math.sql
index e89991c..f509555 100644
--- a/db/math.sql
+++ b/db/math.sql
@@ -16,7 +16,7 @@
-- HTML output from texvc, if any
math_html text,
- -- MathML output from texvc, if any
+ -- MathML output from texvc, or from LaTeXML
math_mathml text
) /*$wgDBTableOptions*/;
diff --git a/tests/MathDatabaseTest.php b/tests/MathDatabaseTest.php
index f909f7f..99fb00e 100644
--- a/tests/MathDatabaseTest.php
+++ b/tests/MathDatabaseTest.php
@@ -72,8 +72,8 @@
// comparing the class object does now work due to null values
etc.
// $this->assertEquals($this->renderer,$renderer2);
$this->assertEquals( $this->renderer->getTex(),
$renderer2->getTex(), "test if tex is the same" );
- $this->assertEquals( $this->renderer->mathml,
$renderer2->mathml, "Check MathML encoding" );
- $this->assertEquals( $this->renderer->html, $renderer2->html );
+ $this->assertEquals( $this->renderer->getMathml(),
$renderer2->getMathml(), "Check MathML encoding" );
+ $this->assertEquals( $this->renderer->getHtml(),
$renderer2->getHtml() );
}
diff --git a/tests/MathLaTeXMLTest.php b/tests/MathLaTeXMLTest.php
new file mode 100644
index 0000000..30adf0d
--- /dev/null
+++ b/tests/MathLaTeXMLTest.php
@@ -0,0 +1,146 @@
+<?php
+/**
+* Test the LaTeXML output format.
+*
+* @group Math
+*/
+class MathLaTeXMLTest extends MediaWikiTestCase {
+
+ // State-variables for HTTP Mockup classes
+ public static $content = null;
+ public static $good = false;
+ public static $html = false;
+ public static $timeout = false;
+
+ /**
+ * Set the mock values for the HTTP Mockup classes
+ *
+ * @param boolean $good
+ * @param mixed $html HTML of the error message or false if no error is
present.
+ * @param boolean $timeout true if
+ */
+ public static function setMockValues( $good, $html, $timeout ) {
+ self::$good = $good;
+ self::$html = $html;
+ self::$timeout = $timeout;
+ }
+
+ /**
+ * Tests behavior of makeRequest() that communicates with the host.
+ * Testcase: Invalid request.
+ * @covers MathTexvc::makeRequest
+ */
+ public function testMakeRequestInvalid() {
+ self::setMockValues( false, false, false );
+ $url = 'http://example.com/invalid';
+
+ $renderer = $this->getMockBuilder( 'MathLaTeXML' )
+ ->setMethods( NULL )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $requestReturn = $renderer->makeRequest( $url, 'a+b', $res,
$error
+ , 'LaTeXMLHttpRequestTester' );
+ $this->assertEquals( false, $requestReturn
+ , "requestReturn is false if HTTP::post returns false."
);
+ $this->assertEquals( false, $res
+ , "res is false if HTTP:post returns false." );
+ $errmsg = wfMessage( 'math_latexml_invalidresponse' , $url )
+ ->inContentLanguage()->escaped();
+ $this->assertContains( $errmsg, $error
+ , "return an error if HTTP::post returns false" );
+ }
+
+ /**
+ * Tests behavior of makeRequest() that communicates with the host.
+ * Testcase: Valid request.
+ * @covers MathTexvc::makeRequest
+ */
+ public function testMakeRequestSuccess() {
+ self::setMockValues( true, true, false );
+ $url = 'http://example.com/valid';
+ $renderer = $this->getMockBuilder( 'MathLaTeXML' )
+ ->setMethods( NULL )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $requestReturn = $renderer->makeRequest( $url, 'a+b', $res,
$error
+ , 'LaTeXMLHttpRequestTester' );
+ $this->assertEquals( true, $requestReturn, "successful call
return" );
+ $this->isTrue( $res, "successfull call" );
+ $this->assertEquals( $error,'', "successfull call errormessage"
);
+ }
+
+ /**
+ * Tests behavior of makeRequest() that communicates with the host.
+ * Testcase: Timeout.
+ * @covers MathTexvc::makeRequest
+ */
+ public function testMakeRequestTimeout() {
+ self::setMockValues( false, true, true );
+ $url = 'http://example.com/timeout';
+ $renderer = $this->getMockBuilder( 'MathLaTeXML' )
+ ->setMethods( NULL )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $requestReturn = $renderer->makeRequest( $url,
'$\longcommand$', $res
+ , $error, 'LaTeXMLHttpRequestTester' );
+ $this->assertEquals( false, $requestReturn, "timeout call
return" );
+ $this->assertEquals( false, $res, "timeout call return" );
+ $errmsg = wfMessage( 'math_latexml_timeout', $url )
+ ->inContentLanguage()->escaped();
+ $this->assertContains( $errmsg, $error, "timeout call
errormessage" );
+ }
+
+ /**
+ * Checks the basic functionallity
+ * i.e. if the span element is generated right.
+ */
+ public function testIntegration() {
+ global $wgLaTeXMLTimeout;
+ $wgLaTeXMLTimeout = 20;
+ $renderer = MathRenderer::getRenderer( "a+b", array(),
MW_MATH_LATEXML );
+ $real = $renderer->render( true );
+ $expected = '<span class="tex" dir="ltr" id="a_b"><math
xmlns="http://www.w3.org/1998/Math/MathML" id="p1.1.m1" class="ltx_Math"
alttext="a+b" xml:id="p1.1.m1.1" display="inline" xref="p1.1.m1.1.cmml">
<semantics xml:id="p1.1.m1.1a" xref="p1.1.m1.1.cmml"> <mrow
xml:id="p1.1.m1.1.4" xref="p1.1.m1.1.4.cmml"> <mi xml:id="p1.1.m1.1.1"
xref="p1.1.m1.1.1.cmml">a</mi> <mo xml:id="p1.1.m1.1.2"
xref="p1.1.m1.1.2.cmml">+</mo> <mi xml:id="p1.1.m1.1.3"
xref="p1.1.m1.1.3.cmml">b</mi> </mrow> <annotation-xml
xml:id="p1.1.m1.1.cmml" encoding="MathML-Content" xref="p1.1.m1.1">
<apply xml:id="p1.1.m1.1.4.cmml" xref="p1.1.m1.1.4"> <plus
xml:id="p1.1.m1.1.2.cmml" xref="p1.1.m1.1.2"/> <ci
xml:id="p1.1.m1.1.1.cmml" xref="p1.1.m1.1.1">a</ci> <ci
xml:id="p1.1.m1.1.3.cmml" xref="p1.1.m1.1.3">b</ci> </apply>
</annotation-xml> <annotation xml:id="p1.1.m1.1b"
encoding="application/x-tex" xref="p1.1.m1.1.cmml">a+b</annotation>
</semantics> </math></span>';
+ $this->assertEquals( $expected, $real
+ , "Rendering of a+b in plain Text mode" );
+ }
+}
+
+/**
+ * Helper class for testing
+ * @author physikerwelt
+ * @see MWHttpRequestTester
+ *
+ */
+class LaTeXMLHttpRequestTester {
+ public static function factory() {
+ return new LaTeXMLHttpRequestTester();
+ }
+ public static function execute() {
+ return new LaTeXMLTestStatus();
+ }
+ public static function getContent() {
+ return MathLaTeXMLTest::$content;
+ }
+}
+
+/**
+ * Helper class for testing
+ * @author physikerwelt
+ * @see Status
+ */
+class LaTeXMLTestStatus {
+ static function isGood() {
+ return MathLaTeXMLTest::$good;
+ }
+
+ static function hasMessage( $s ) {
+ if ( $s == 'http-timed-out' ) {
+ return MathLaTeXMLTest::$timeout;
+ } else {
+ return false;
+ }
+ }
+ static function getHtml() {
+ return MathLaTeXMLTest::$html;
+ }
+}
\ No newline at end of file
diff --git a/tests/MathRendererTest.php b/tests/MathRendererTest.php
index ea6c96b..325fcac 100644
--- a/tests/MathRendererTest.php
+++ b/tests/MathRendererTest.php
@@ -63,4 +63,14 @@
$this->assertEquals( $renderer->isChanged(), true
, "assumes that changing a hash sets changed to true");
}
+
+ public function testSetPurge(){
+ $renderer = $this->getMockBuilder( 'MathRenderer' )
+ ->setMethods( array( 'render' ) )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $renderer->setPurge();
+ $this->assertEquals( $renderer->isPurge(), true, "Test purge."
);
+
+ }
}
\ No newline at end of file
--
To view, visit https://gerrit.wikimedia.org/r/61987
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I5d29e219c0d3b907e22ea0bb3b30f000d8a7a9f8
Gerrit-PatchSet: 34
Gerrit-Project: mediawiki/extensions/Math
Gerrit-Branch: master
Gerrit-Owner: Physikerwelt <[email protected]>
Gerrit-Reviewer: Cjucovschi <[email protected]>
Gerrit-Reviewer: Deyan <[email protected]>
Gerrit-Reviewer: JanZerebecki <[email protected]>
Gerrit-Reviewer: Mattflaschen <[email protected]>
Gerrit-Reviewer: MaxSem <[email protected]>
Gerrit-Reviewer: Ori.livneh <[email protected]>
Gerrit-Reviewer: Physikerwelt <[email protected]>
Gerrit-Reviewer: PleaseStand <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: TheDJ <[email protected]>
Gerrit-Reviewer: Worden.lee <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits