Fix MathJax centers equations

* Removes the MathJax heuristics that decides
  if equations are centered or left-aligned.
* Introduces the attribute display to specify
  if the math element is rendered in inline,
  display, or inline-displaystyle.
* add css rules for display / inline math images

Bug: 61051
Change-Id: Iba69903f781f0cb1606b8ddcffb90fb86c9b229b
This commit is contained in:
Moritz Schubotz (Physikerwelt) 2014-03-17 06:14:02 +00:00
parent 24f2ed2c5e
commit c5b0b15d8f
12 changed files with 161 additions and 45 deletions

View File

@ -125,6 +125,7 @@ class MathHooks {
if ( $wgUseMathJax && $mode == MW_MATH_MATHJAX ) {
$parser->getOutput()->addModules( array( 'ext.math.mathjax.enabler' ) );
}
$parser->getOutput()->addModuleStyles( array( 'ext.math.styles' ) );
$renderer->writeCache();
$result = $wgContLang->armourMath( $renderedMath );

View File

@ -41,6 +41,16 @@ define( 'MW_MATH_MATHJAX', 6 ); /// new in 1.19/1.20
define( 'MW_MATH_LATEXML', 7 ); /// new in 1.22
/**@}*/
/**@{
* Mathstyle constants
*/
define( 'MW_MATHSTYLE_INLINE_DISPLAYSTYLE', 0 ); //default large operator inline
define( 'MW_MATHSTYLE_DISPLAY', 1 ); // large operators centered in a new line
define( 'MW_MATHSTYLE_INLINE', 2 ); // small operators inline
// There is no style which renders small operators
// but display the equation centered in a new line.
/**@}*/
/** Location of the texvc binary */
$wgTexvc = __DIR__ . '/math/texvc';
/**
@ -168,6 +178,12 @@ $wgExtensionMessagesFiles['Math'] = $dir . 'Math.i18n.php';
$wgParserTestFiles[] = $dir . 'mathParserTests.txt';
$wgResourceModules['ext.math.styles'] = array(
'localBasePath' => __DIR__ . '/modules',
'remoteExtPath' => 'Math/modules',
'styles' => 'ext.math.css',
);
// MathJax module
// If you modify these arrays, update ext.math.mathjax.enabler.js to ensure
// that getModuleNameFromFile knows how to map files to MediaWiki modules.

View File

@ -183,9 +183,18 @@ class MathLaTeXML extends MathRenderer {
* @return string HTTP POST data
*/
public function getPostData() {
$texcmd = urlencode( $this->tex );
$settings = $this->serializeSettings( $this->getLaTeXMLSettings() );
return $settings . '&tex=' . $texcmd;
$tex = $this->getTex();
if ( $this->getMathStyle() == MW_MATHSTYLE_INLINE_DISPLAYSTYLE ) {
// In MW_MATHSTYLE_INLINE_DISPLAYSTYLE the old
// texvc behavior is reproduced:
// The equation is rendered in displaystyle
// (texvc used $$ $tex $$ to render)
// but the equation is not centered.
$tex = '{\displaystyle ' . $tex . '}';
}
$texcmd = rawurlencode( $tex );
$settings = $this->serializeSettings( $this->getLaTeXMLSettings( ) );
return $settings. '&tex=' . $texcmd;
}
/**
* Does the actual web request to convert TeX to MathML.

View File

@ -29,6 +29,8 @@ abstract class MathRenderer {
protected $tex = '';
/** @var string the original user input string (which was used to caculate the inputhash) */
protected $userInputTex = '';
/** @var (MW_MATHSTYLE_INLINE_DISPLAYSTYLE|MW_MATHSTYLE_DISPLAY|MW_MATHSTYLE_INLINE) the rendering style */
protected $mathStyle = MW_MATHSTYLE_INLINE_DISPLAYSTYLE;
/**
* is calculated by texvc.
* @var string
@ -84,6 +86,27 @@ abstract class MathRenderer {
*/
public static function getRenderer( $tex, $params = array(), $mode = MW_MATH_PNG ) {
global $wgDefaultUserOptions;
$mathStyle = null;
if ( isset( $params['display'] ) ) {
$layoutMode = $params['display'];
if ( $layoutMode == 'block' ) {
$mathStyle = MW_MATHSTYLE_DISPLAY ;
// TODO: Implement caching for attributes of the math tag
// Currently the key for the database entry relating to an equation
// is md5($tex) the new option to determine if the tex input
// is rendered in displaystyle or textstyle would require a database
// layout change to use a composite key e.g. (md5($tex),$mathStyle).
// As a workaround we use the prefix \displaystyle so that the key becomes
// md5((\{\\displaystyle|\{\\textstyle)?\s?$tex\}?)
// The new value of $tex string describes now how the rendering should look like.
// The variable MathRenderer::mathStyle determines if the rendered equation should
// be centered in a new line, or just in be displayed in the current line.
$tex = '{\displaystyle ' . $tex . '}';
} elseif ( $layoutMode == 'inline' ) {
$mathStyle = MW_MATHSTYLE_INLINE;
$tex = '{\textstyle ' . $tex . '}';
}
}
$validModes = array( MW_MATH_PNG, MW_MATH_SOURCE, MW_MATH_MATHJAX, MW_MATH_LATEXML );
if ( !in_array( $mode, $validModes ) )
$mode = $wgDefaultUserOptions['math'];
@ -100,6 +123,7 @@ abstract class MathRenderer {
$renderer = new MathTexvc( $tex, $params );
}
wfDebugLog ( "Math", 'start rendering $' . $renderer->tex . '$ in mode ' . $mode );
$renderer->setMathStyle( $mathStyle );
return $renderer;
}
@ -422,6 +446,26 @@ abstract class MathRenderer {
return $this->lastError;
}
/**
*
* @param (MW_MATHSTYLE_INLINE_DISPLAYSTYLE|MW_MATHSTYLE_DISPLAY|MW_MATHSTYLE_INLINE) $mathStyle
*/
public function setMathStyle( $displayStyle = MW_MATHSTYLE_DISPLAY ) {
if ( $this->mathStyle !== $displayStyle ){
$this->changed = true;
}
$this->mathStyle = $displayStyle;
}
/**
* Returns the value of the DisplayStyle attribute
* @return (MW_MATHSTYLE_INLINE_DISPLAYSTYLE|MW_MATHSTYLE_DISPLAY|MW_MATHSTYLE_INLINE) the DisplayStyle
*/
public function getMathStyle() {
return $this->mathStyle;
}
/**
* Get if the input tex was marked as secure
* @return boolean

View File

@ -27,11 +27,18 @@ class MathSource extends MathRenderer {
function render() {
# No need to render or parse anything more!
# New lines are replaced with spaces, which avoids confusing our parser (bugs 23190, 22818)
if ( $this->getMathStyle() == MW_MATHSTYLE_DISPLAY ) {
$class = 'mwe-math-fallback-source-display';
} else {
$class = 'mwe-math-fallback-source-inline';
}
return Xml::element( 'span',
$this->getAttributes(
'span',
array(
'class' => 'tex',
// the former class name was 'tex'
// for backwards compatibility we keep this classname
'class' => $class. ' tex',
'dir' => 'ltr'
)
),

View File

@ -79,19 +79,26 @@ class MathTexvc extends MathRenderer {
*/
public function getMathImageHTML() {
$url = $this->getMathImageUrl();
$attributes = array(
// the former class name was 'tex'
// for backwards compatibility we keep that classname
'class' => 'mwe-math-fallback-png-inline tex',
'alt' => $this->getTex()
);
if ( $this->getMathStyle() === MW_MATHSTYLE_DISPLAY ){
// if DisplayStyle is true, the equation will be centered in a new line
$attributes[ 'class' ] = 'mwe-math-fallback-png-display tex';
}
return Xml::element( 'img',
$this->getAttributes(
'img',
array(
'class' => 'tex',
'alt' => $this->getTex(),
),
$attributes,
array(
'src' => $url
)
)
);
}
/**

16
README
View File

@ -35,6 +35,22 @@ if ( typeof mathJax === 'undefined' ) {
};
}
Attributes of the <math /> element:
attribute "display":
possible values: "inline", "block" or "inline-displaystyle" (default)
"display" reproduces the old texvc behavior:
The equation is rendered with large height operands (texvc used $$ $tex $$ to render)
but the equation printed to the current line of the output and not centered in a new line.
In Wikipedia users use :<math>$tex</math> to move the math element closer to the center.
"inline" renders the equation in with small height operands by adding {\textstyle $tex } to the
users input ($tex). The equation is displayed in the current text line.
"inline-displaystyle" renders the equation in with large height operands centered in a new line by adding
{\displaystyle $tex } to the user input ($tex).
For testing your installation run
php tests/phpunit/phpunit.php extensions/Math/tests/
from your MediWiki home path.

View File

@ -20,7 +20,8 @@ MathJax.Extension.wiki2jax = {
this.configured = true;
}
var that = this;
$('span.tex, img.tex, strong.texerror', element || document).each(function(i, span) {
$('.mwe-math-fallback-png-display, .mwe-math-fallback-png-inline, .mwe-math-fallback-source-display,'+
'.mwe-math-fallback-source-inline, strong.texerror', element || document).each(function(i, span) {
that.ConvertMath(span);
});
},
@ -37,7 +38,7 @@ MathJax.Extension.wiki2jax = {
ConvertMath: function (node) {
var parent = node.parentNode,
mode = parent.tagName === "DD" && parent.childNodes.length === 1 ? "; mode=display" : "",
mode = "", //Bug 61051 (heuristic unwanted by the community)
tex;
if (node.nodeName == 'IMG') {
tex = node.alt;
@ -49,7 +50,9 @@ MathJax.Extension.wiki2jax = {
}
tex = tex.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&nbsp;/g," ");
}
if ( $( node ).hasClass( "mwe-math-fallback-png-display") || $( node ).hasClass( "mwe-math-fallback-source-display") ){
mode = "; mode=display";
}
// We don't allow comments (%) in texvc and escape all literal % by default.
tex = tex.replace(/([^\\])%/g, "$1\\%" );

12
modules/ext.math.css Normal file
View File

@ -0,0 +1,12 @@
/*
Document : ext.math
Created on : 23.09.2013, 13:55:00
Author : Physikerwelt (Moritz Schubotz)
Description:
Shows browser-dependent math output.
*/
.mwe-math-fallback-png-inline { display: inline; vertical-align: middle}
.mwe-math-fallback-png-display { display: block; margin-left: auto; margin-right: auto;}
.mwe-math-fallback-source-inline { display: inline; vertical-align: middle}
.mwe-math-fallback-source-display { display: block; margin-left: auto; margin-right: auto;}

View File

@ -142,9 +142,10 @@ class MathLaTeXMLTest extends MediaWikiTestCase {
$this->setMwGlobals( 'wgMathLaTeXMLTimeout', 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" display="inline" xml:id="p1.1.m1.1" 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 encoding="MathML-Content" xml:id="p1.1.m1.1.cmml" 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 encoding="application/x-tex" xml:id="p1.1.m1.1b" xref="p1.1.m1.1.cmml">a+b</annotation> </semantics> </math></span>';
$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="{\displaystyle a+b}" display="inline" xml:id="p1.1.m1.1" 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 encoding="MathML-Content" xml:id="p1.1.m1.1.cmml" 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 encoding="application/x-tex" xml:id="p1.1.m1.1b" xref="p1.1.m1.1.cmml">{\displaystyle a+b}</annotation> </semantics> </math></span>';
$this->assertEquals( $expected, $real
, "Rendering of a+b in plain Text mode" );
, "Rendering of a+b in plain Text mode." .
$renderer->getLastError() );
}
}
@ -186,4 +187,4 @@ class LaTeXMLTestStatus {
static function getHtml() {
return MathLaTeXMLTest::$html;
}
}
}

View File

@ -12,7 +12,7 @@ class MathSourceTest extends MediaWikiTestCase {
public function testBasics() {
$real = MathRenderer::renderMath( "a+b", array(), MW_MATH_SOURCE );
$this->assertEquals(
'<span class="tex" dir="ltr">$ a+b $</span>',
'<span class="mwe-math-fallback-source-inline tex" dir="ltr">$ a+b $</span>',
$real,
"Rendering of a+b in plain Text mode"
);
@ -24,7 +24,7 @@ class MathSourceTest extends MediaWikiTestCase {
public function testNewLines() {
$real = MathRenderer::renderMath( "a\n b", array(), MW_MATH_SOURCE );
$this->assertSame(
'<span class="tex" dir="ltr">$ a b $</span>',
'<span class="mwe-math-fallback-source-inline tex" dir="ltr">$ a b $</span>',
$real,
"converting newlines to spaces"
);

File diff suppressed because one or more lines are too long