Add experimental MathML output option for math (only works with some
browsers and requires use of an XML content type; try setting $wgMimeType = "application/xhtml+xml" and use Mozilla). Rearranged a couple things in prefs. Did some refactoring in Math.php to remove some duplicated code and figure out what is going on.
This commit is contained in:
parent
65b84317c9
commit
93b09379fb
6 changed files with 233 additions and 168 deletions
|
|
@ -1,153 +1,205 @@
|
|||
<?php
|
||||
#
|
||||
# Takes LaTeX fragments, sends them to a helper program (texvc) for rendering
|
||||
# to rasterized PNG and HTML and MathML approximations. An appropriate
|
||||
# rendering form is picked and returned.
|
||||
#
|
||||
# by Tomasz Wegrzanowski, with additions by Brion Vibber (2003, 2004)
|
||||
#
|
||||
|
||||
function linkToMathImage ( $tex, $outputhash )
|
||||
{
|
||||
global $wgMathPath;
|
||||
$url = htmlspecialchars( "$wgMathPath/$outputhash.png" );
|
||||
$alt = htmlspecialchars( $tex );
|
||||
return "<img class='tex' src=\"$url\" alt=\"$alt\" />";
|
||||
}
|
||||
|
||||
function renderMath( $tex )
|
||||
{
|
||||
global $wgUser, $wgMathDirectory, $wgTmpDirectory, $wgInputEncoding;
|
||||
global $wgTexvc;
|
||||
$mf = wfMsg( "math_failure" );
|
||||
$munk = wfMsg( "math_unknown_error" );
|
||||
|
||||
$fname = "renderMath";
|
||||
|
||||
$math = $wgUser->getOption("math");
|
||||
if( $math == 3 ) {
|
||||
return ('$ '.wfEscapeHTML($tex).' $');
|
||||
class MathRenderer {
|
||||
var $mode = MW_MATH_MODERN;
|
||||
var $tex = "";
|
||||
var $inputhash = "";
|
||||
var $hash = "";
|
||||
var $html = "";
|
||||
var $mathml = "";
|
||||
var $conservativeness = 0;
|
||||
|
||||
function MathRenderer( $tex ) {
|
||||
$this->tex = $tex;
|
||||
}
|
||||
|
||||
function setOutputMode( $mode ) {
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
$md5 = md5($tex);
|
||||
$md5_sql = mysql_escape_string(pack("H32", $md5));
|
||||
if ($math == 0) {
|
||||
$sql = "SELECT math_outputhash FROM math WHERE math_inputhash = '$md5_sql'";
|
||||
} else {
|
||||
$sql = "SELECT math_outputhash,math_html_conservativeness,math_html FROM math WHERE math_inputhash = '$md5_sql'";
|
||||
}
|
||||
|
||||
$res = wfQuery( $sql, DB_READ, $fname );
|
||||
|
||||
if( $rpage = wfFetchObject ( $res ) ) {
|
||||
$outputhash = unpack( "H32md5", $rpage->math_outputhash . " " );
|
||||
$outputhash = $outputhash ['md5'];
|
||||
if( file_exists( "$wgMathDirectory/$outputhash.png" ) ) {
|
||||
if (($math == 0) || ($rpage->math_html == '') || (($math == 1) && ($rpage->math_html_conservativeness != 2)) || (($math == 4) && ($rpage->math_html_conservativeness == 0))) {
|
||||
return linkToMathImage ( $tex, $outputhash );
|
||||
function render() {
|
||||
global $wgMathDirectory, $wgTmpDirectory, $wgInputEncoding;
|
||||
global $wgTexvc;
|
||||
|
||||
if( $this->mode == MW_MATH_SOURCE ) {
|
||||
# No need to render or parse anything more!
|
||||
return ('$ '.htmlspecialchars( $tex ).' $');
|
||||
}
|
||||
|
||||
if( !$this->_recall() ) {
|
||||
# Ensure that the temp and output directories are available before continuing...
|
||||
if( !file_exists( $wgMathDirectory ) ) {
|
||||
if( !@mkdir( $wgMathDirectory ) ) {
|
||||
return $this->_error( "math_bad_output" );
|
||||
}
|
||||
} elseif( !is_dir( $wgMathDirectory ) || !is_writable( $wgMathDirectory ) ) {
|
||||
return $this->_error( "math_bad_output" );
|
||||
}
|
||||
if( !file_exists( $wgTmpDirectory ) ) {
|
||||
if( !@mkdir( $wgTmpDirectory ) ) {
|
||||
return $this->_error( "math_bad_tmpdir" );
|
||||
}
|
||||
} elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) {
|
||||
return $this->_error( "math_bad_tmpdir" );
|
||||
}
|
||||
|
||||
if( !is_executable( $wgTexvc ) ) {
|
||||
return $this->_error( "math_notexvc" );
|
||||
}
|
||||
$cmd = $wgTexvc." ".
|
||||
escapeshellarg($wgTmpDirectory)." ".
|
||||
escapeshellarg($wgMathDirectory)." ".
|
||||
escapeshellarg($this->tex)." ".
|
||||
escapeshellarg($wgInputEncoding);
|
||||
wfDebug( "TeX: $cmd" );
|
||||
$contents = `$cmd`;
|
||||
|
||||
if (strlen($contents) == 0) {
|
||||
return $this->_error( "math_unknown_error" );
|
||||
}
|
||||
|
||||
$retval = substr ($contents, 0, 1);
|
||||
if (($retval == "C") || ($retval == "M") || ($retval == "L")) {
|
||||
if ($retval == "C")
|
||||
$this->conservativeness = 2;
|
||||
else if ($retval == "M")
|
||||
$this->conservativeness = 1;
|
||||
else
|
||||
$this->conservativeness = 0;
|
||||
$outdata = substr ($contents, 33);
|
||||
|
||||
$i = strpos($outdata, "\000");
|
||||
|
||||
$this->html = substr($outdata, 0, $i);
|
||||
$this->mathml = substr($outdata, $i+1);
|
||||
|
||||
$sql_html = "'".wfStrencode($this->html)."'";
|
||||
$sql_mathml = "'".wfStrencode($this->mathml)."'";
|
||||
} else if (($retval == "c") || ($retval == "m") || ($retval == "l")) {
|
||||
$this->html = substr ($contents, 33);
|
||||
if ($retval == "c")
|
||||
$this->conservativeness = 2;
|
||||
else if ($retval == "m")
|
||||
$this->conservativeness = 1;
|
||||
else
|
||||
$this->conservativeness = 0;
|
||||
$sql_html = "'".wfStrencode($this->html)."'";
|
||||
$this->mathml = '';
|
||||
$sql_mathml = 'NULL';
|
||||
} else if ($retval == "X") {
|
||||
$outhtml = '';
|
||||
$this->mathml = substr ($contents, 33);
|
||||
$sql_html = 'NULL';
|
||||
$sql_mathml = "'".wfStrencode($this->mathml)."'";
|
||||
$this->conservativeness = 0;
|
||||
} else if ($retval == "+") {
|
||||
$this->outhtml = '';
|
||||
$this->mathml = '';
|
||||
$sql_html = 'NULL';
|
||||
$sql_mathml = 'NULL';
|
||||
$this->conservativeness = 0;
|
||||
} else {
|
||||
return $rpage->math_html;
|
||||
$errbit = htmlspecialchars( substr($contents, 1) );
|
||||
switch( $retval ) {
|
||||
case "E": return $this->_error( "math_lexing_error", $errbit );
|
||||
case "S": return $this->_error( "math_syntax_error", $errbit );
|
||||
case "F": return $this->_error( "math_unknown_function", $errbit );
|
||||
default: return $this->_error( "math_unknown_error", $errbit );
|
||||
}
|
||||
}
|
||||
|
||||
$this->hash = substr ($contents, 1, 32);
|
||||
if (!preg_match("/^[a-f0-9]{32}$/", $this->hash)) {
|
||||
return $this->_error( "math_unknown_error" );
|
||||
}
|
||||
|
||||
if( !file_exists( "$wgMathDirectory/{$this->hash}.png" ) ) {
|
||||
return $this->_error( "math_image_error" );
|
||||
}
|
||||
|
||||
# Now save it back to the DB:
|
||||
$outmd5_sql = wfStrencode(pack("H32", $this->hash));
|
||||
|
||||
$md5_sql = wfStrencode( pack("H32", $this->md5) ); # Binary packed, not hex
|
||||
$sql = "REPLACE INTO math VALUES ('".$md5_sql."', '".$outmd5_sql."', ".$this->conservativeness.", ".$sql_html.", ".$sql_mathml.")";
|
||||
|
||||
$res = wfQuery( $sql, DB_READ, "MathRenderer::render" );
|
||||
# we don't really care if it fails
|
||||
}
|
||||
|
||||
return $this->_doRender();
|
||||
}
|
||||
|
||||
function _error( $msg, $append = "" ) {
|
||||
$mf = htmlspecialchars( wfMsg( "math_failure" ) );
|
||||
$munk = htmlspecialchars( wfMsg( "math_unknown_error" ) );
|
||||
$errmsg = htmlspecialchars( wfMsg( $msg ) );
|
||||
$source = htmlspecialchars($this->tex);
|
||||
return "<strong class='error'>$mf ($errmsg$append): $source</strong>\n";
|
||||
}
|
||||
|
||||
function _recall() {
|
||||
global $wgMathDirectory;
|
||||
|
||||
$this->md5 = md5( $this->tex );
|
||||
|
||||
$md5_sql = wfStrencode( pack("H32", $this->md5) ); # Binary packed, not hex
|
||||
$sql = "SELECT math_outputhash,math_html_conservativeness,math_html,math_mathml FROM math WHERE math_inputhash = '$md5_sql'";
|
||||
$res = wfQuery( $sql, DB_READ, "MathRenderer::_recall" );
|
||||
|
||||
if( $rpage = wfFetchObject ( $res ) ) {
|
||||
# Tailing 0x20s can get dropped by the database, add it back on if necessary:
|
||||
$xhash = unpack( "H32md5", $rpage->math_outputhash . " " );
|
||||
$this->hash = $xhash ['md5'];
|
||||
|
||||
$this->conservativeness = $rpage->math_html_conservativeness;
|
||||
$this->html = $rpage->math_html;
|
||||
$this->mathml = $rpage->math_mathml;
|
||||
|
||||
if( file_exists( "$wgMathDirectory/{$this->hash}.png" ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
# Missing from the database and/or the render cache
|
||||
return false;
|
||||
}
|
||||
|
||||
# Ensure that the temp and output directories are available before continuing...
|
||||
if( !file_exists( $wgMathDirectory ) ) {
|
||||
if( !@mkdir( $wgMathDirectory ) ) {
|
||||
return "<b>$mf (" . wfMsg( "math_bad_output" ) . ")</b>";
|
||||
|
||||
# Select among PNG, HTML, or MathML output depending on
|
||||
function _doRender() {
|
||||
if( $this->mode == MW_MATH_MATHML && $this->mathml != '' ) {
|
||||
return "<math xmlns='http://www.w3.org/1998/Math/MathML'>{$this->mathml}</math>";
|
||||
}
|
||||
} elseif( !is_dir( $wgMathDirectory ) || !is_writable( $wgMathDirectory ) ) {
|
||||
return "<b>$mf (" . wfMsg( "math_bad_output" ) . ")</b>";
|
||||
}
|
||||
if( !file_exists( $wgTmpDirectory ) ) {
|
||||
if( !@mkdir( $wgTmpDirectory ) ) {
|
||||
return "<b>$mf (" . wfMsg( "math_bad_tmpdir" ) . ")</b>";
|
||||
if (($this->mode == MW_MATH_PNG) || ($this->html == '') ||
|
||||
(($this->mode == MW_MATH_SIMPLE) && ($this->conservativeness != 2)) ||
|
||||
(($this->mode == MW_MATH_MODERN || $this->mode == MW_MATH_MATHML) && ($this->conservativeness == 0))) {
|
||||
return $this->_linkToMathImage();
|
||||
} else {
|
||||
return $this->html;
|
||||
}
|
||||
} elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) {
|
||||
return "<b>$mf (" . wfMsg( "math_bad_tmpdir" ) . ")</b>";
|
||||
}
|
||||
|
||||
if( !is_executable( $wgTexvc ) ) {
|
||||
return "<b>$mf (" . wfMsg( "math_notexvc" ) . ")</b>";
|
||||
}
|
||||
$cmd = $wgTexvc." ".
|
||||
escapeshellarg($wgTmpDirectory)." ".
|
||||
escapeshellarg($wgMathDirectory)." ".
|
||||
escapeshellarg($tex)." ".
|
||||
escapeshellarg($wgInputEncoding);
|
||||
wfDebug( "TeX: $cmd" );
|
||||
$contents = `$cmd`;
|
||||
|
||||
if (strlen($contents) == 0) {
|
||||
return "<b>".$mf." (".$munk."): ".wfEscapeHTML($tex)."</b>";
|
||||
}
|
||||
|
||||
$retval = substr ($contents, 0, 1);
|
||||
if (($retval == "C") || ($retval == "M") || ($retval == "L")) {
|
||||
if ($retval == "C")
|
||||
$conservativeness = 2;
|
||||
else if ($retval == "M")
|
||||
$conservativeness = 1;
|
||||
else
|
||||
$conservativeness = 0;
|
||||
$outdata = substr ($contents, 33);
|
||||
|
||||
$i = strpos($outdata, "\000");
|
||||
|
||||
$outhtml = substr($outdata, 0, $i);
|
||||
$mathml = substr($outdata, $i+1);
|
||||
|
||||
$sql_html = "'".mysql_escape_string($outhtml)."'";
|
||||
$sql_mathml = "'".mysql_escape_string($mathml)."'";
|
||||
} else if (($retval == "c") || ($retval == "m") || ($retval == "l")) {
|
||||
$outhtml = substr ($contents, 33);
|
||||
if ($retval == "c")
|
||||
$conservativeness = 2;
|
||||
else if ($retval == "m")
|
||||
$conservativeness = 1;
|
||||
else
|
||||
$conservativeness = 0;
|
||||
$sql_html = "'".mysql_escape_string($outhtml)."'";
|
||||
$mathml = '';
|
||||
$sql_mathml = 'NULL';
|
||||
} else if ($retval == "X") {
|
||||
$outhtml = '';
|
||||
$mathml = substr ($contents, 33);
|
||||
$sql_html = 'NULL';
|
||||
$sql_mathml = "'".mysql_escape_string($mathml)."'";
|
||||
$conservativeness = 0;
|
||||
} else if ($retval == "+") {
|
||||
$outhtml = '';
|
||||
$mathml = '';
|
||||
$sql_html = 'NULL';
|
||||
$sql_mathml = 'NULL';
|
||||
$conservativeness = 0;
|
||||
} else {
|
||||
if ($retval == "E")
|
||||
$errmsg = wfMsg( "math_lexing_error" );
|
||||
else if ($retval == "S")
|
||||
$errmsg = wfMsg( "math_syntax_error" );
|
||||
else if ($retval == "F")
|
||||
$errmsg = wfMsg( "math_unknown_function" );
|
||||
else
|
||||
$errmsg = $munk;
|
||||
return "<h3>".$mf." (".$errmsg.substr($contents, 1)."): ".wfEscapeHTML($tex)."</h3>";
|
||||
}
|
||||
|
||||
$outmd5 = substr ($contents, 1, 32);
|
||||
if (!preg_match("/^[a-f0-9]{32}$/", $outmd5)) {
|
||||
return "<b>".$mf." (".$munk."): ".wfEscapeHTML($tex)."</b>";
|
||||
function _linkToMathImage() {
|
||||
global $wgMathPath;
|
||||
$url = htmlspecialchars( "$wgMathPath/{$this->hash}.png" );
|
||||
$alt = htmlspecialchars( $this->tex );
|
||||
return "<img class='tex' src=\"$url\" alt=\"$alt\" />";
|
||||
}
|
||||
|
||||
if( !file_exists( "$wgMathDirectory/$outmd5.png" ) ) {
|
||||
$errmsg = wfMsg( "math_image_error" );
|
||||
return "<h3>$mf ($errmsg): " . wfEscapeHTML($tex) . "</h3>";
|
||||
}
|
||||
}
|
||||
|
||||
$outmd5_sql = mysql_escape_string(pack("H32", $outmd5));
|
||||
|
||||
$sql = "REPLACE INTO math VALUES ('".$md5_sql."', '".$outmd5_sql."', ".$conservativeness.", ".$sql_html.", ".$sql_mathml.")";
|
||||
|
||||
$res = wfQuery( $sql, DB_READ, $fname );
|
||||
# we don't really care if it fails
|
||||
|
||||
if (($math == 0) || ($rpage->math_html == '') || (($math == 1) && ($conservativeness != 2)) || (($math == 4) && ($conservativeness == 0)))
|
||||
return linkToMathImage($tex, $outmd5);
|
||||
else
|
||||
return $outhtml;
|
||||
function renderMath( $tex ) {
|
||||
global $wgUser;
|
||||
$math = new MathRenderer( $tex );
|
||||
$math->setOutputMode( $wgUser->getOption("math"));
|
||||
return $math->render();
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
define("RDF_TYPE_PREFS", "application/rdf+xml,text/xml;q=0.7,application/xml;q=0.5,text/rdf;q=0.1");
|
||||
|
||||
|
||||
function wfDublinCoreRdf($article) {
|
||||
|
||||
$url = dcReallyFullUrl($article->mTitle);
|
||||
|
|
|
|||
|
|
@ -321,17 +321,24 @@ class PreferencesForm {
|
|||
$wgOut->addHTML( "<form id=\"preferences\" name=\"preferences\" action=\"$action\"
|
||||
method=\"post\">" );
|
||||
|
||||
# Quickbar setting
|
||||
# First section: identity
|
||||
# Email, etc.
|
||||
#
|
||||
$wgOut->addHtml( "<fieldset>\n<legend>$qb:</legend>\n" );
|
||||
for ( $i = 0; $i < count( $qbs ); ++$i ) {
|
||||
if ( $i == $this->mQuickbar ) { $checked = ' checked="checked"'; }
|
||||
else { $checked = ""; }
|
||||
$wgOut->addHTML( "<div><label><input type='radio' name=\"wpQuickbar\"
|
||||
value=\"$i\"$checked /> {$qbs[$i]}</label></div>\n" );
|
||||
}
|
||||
$wgOut->addHtml( "</fieldset>\n\n" );
|
||||
$this->mUserEmail = wfEscapeHTML( $this->mUserEmail );
|
||||
$this->mRealName = wfEscapeHTML( $this->mRealName );
|
||||
$this->mNick = wfEscapeHTML( $this->mNick );
|
||||
if ( $this->mEmailFlag ) { $emfc = 'checked="checked"'; }
|
||||
else { $emfc = ""; }
|
||||
|
||||
$ps = $this->namespacesCheckboxes();
|
||||
|
||||
$wgOut->addHTML( "<fieldset>
|
||||
<legend>Idento</legend>
|
||||
<div><label>$yrn: <input type='text' name=\"wpRealName\" value=\"{$this->mRealName}\" size='20' /></label></div>
|
||||
<div><label>$yem: <input type='text' name=\"wpUserEmail\" value=\"{$this->mUserEmail}\" size='20' /></label></div>
|
||||
<div><label><input type='checkbox' $emfc value=\"1\" name=\"wpEmailFlag\" /> $emf</label></div>
|
||||
<div><label>$ynn: <input type='text' name=\"wpNick\" value=\"{$this->mNick}\" size='12' /></label></div>\n" );
|
||||
|
||||
# Fields for changing password
|
||||
#
|
||||
$this->mOldpass = wfEscapeHTML( $this->mOldpass );
|
||||
|
|
@ -344,7 +351,19 @@ class PreferencesForm {
|
|||
<div><label>$npw: <input type='password' name=\"wpNewpass\" value=\"{$this->mNewpass}\" size='20' /></label></div>
|
||||
<div><label>$rpw: <input type='password' name=\"wpRetypePass\" value=\"{$this->mRetypePass}\" size='20' /></label></div>
|
||||
" . $this->getToggle( "rememberpassword" ) . "
|
||||
</fieldset>\n\n" );
|
||||
</fieldset>\n</fieldset>\n" );
|
||||
|
||||
|
||||
# Quickbar setting
|
||||
#
|
||||
$wgOut->addHtml( "<fieldset>\n<legend>$qb:</legend>\n" );
|
||||
for ( $i = 0; $i < count( $qbs ); ++$i ) {
|
||||
if ( $i == $this->mQuickbar ) { $checked = ' checked="checked"'; }
|
||||
else { $checked = ""; }
|
||||
$wgOut->addHTML( "<div><label><input type='radio' name=\"wpQuickbar\"
|
||||
value=\"$i\"$checked /> {$qbs[$i]}</label></div>\n" );
|
||||
}
|
||||
$wgOut->addHtml( "</fieldset>\n\n" );
|
||||
|
||||
# Skin setting
|
||||
#
|
||||
|
|
@ -414,23 +433,7 @@ class PreferencesForm {
|
|||
<div><input type=\"button\" value=\"$tzGuess\" onClick=\"javascript:guessTimezone()\" /></div>
|
||||
</fieldset>\n\n" );
|
||||
|
||||
# Email, etc.
|
||||
#
|
||||
$this->mUserEmail = wfEscapeHTML( $this->mUserEmail );
|
||||
$this->mRealName = wfEscapeHTML( $this->mRealName );
|
||||
$this->mNick = wfEscapeHTML( $this->mNick );
|
||||
if ( $this->mEmailFlag ) { $emfc = 'checked="checked"'; }
|
||||
else { $emfc = ""; }
|
||||
|
||||
$ps = $this->namespacesCheckboxes();
|
||||
|
||||
$wgOut->addHTML( "<fieldset>
|
||||
<div><label>$yrn: <input type='text' name=\"wpRealName\" value=\"{$this->mRealName}\" size='20' /></label></div>
|
||||
<div><label>$yem: <input type='text' name=\"wpUserEmail\" value=\"{$this->mUserEmail}\" size='20' /></label></div>
|
||||
<div><label><input type='checkbox' $emfc value=\"1\" name=\"wpEmailFlag\" /> $emf</label></div>
|
||||
<div><label>$ynn: <input type='text' name=\"wpNick\" value=\"{$this->mNick}\" size='12' /></label></div>
|
||||
</fieldset>
|
||||
|
||||
$wgOut->addHTML( "
|
||||
<fieldset>
|
||||
<div><label>$rcc: <input type='text' name=\"wpRecent\" value=\"$this->mRecent\" size='6' /></label></div>
|
||||
" . $this->getToggle( "hideminor" ) .
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
# Main wiki script; see design.doc
|
||||
#
|
||||
$wgRequestTime = microtime();
|
||||
|
|
|
|||
|
|
@ -68,12 +68,20 @@ if($wgMetaNamespace === FALSE)
|
|||
'monobook' => "MonoBook"
|
||||
);
|
||||
|
||||
define( "MW_MATH_PNG", 0 );
|
||||
define( "MW_MATH_SIMPLE", 1 );
|
||||
define( "MW_MATH_HTML", 2 );
|
||||
define( "MW_MATH_SOURCE", 3 );
|
||||
define( "MW_MATH_MODERN", 4 );
|
||||
define( "MW_MATH_MATHML", 5 );
|
||||
|
||||
/* private */ $wgMathNamesEn = array(
|
||||
"Always render PNG",
|
||||
"HTML if very simple or else PNG",
|
||||
"HTML if possible or else PNG",
|
||||
"Leave it as TeX (for text browsers)",
|
||||
"Recommended for modern browsers"
|
||||
MW_MATH_PNG => "Always render PNG",
|
||||
MW_MATH_SIMPLE => "HTML if very simple or else PNG",
|
||||
MW_MATH_HTML => "HTML if possible or else PNG",
|
||||
MW_MATH_SOURCE => "Leave it as TeX (for text browsers)",
|
||||
MW_MATH_MODERN => "Recommended for modern browsers",
|
||||
MW_MATH_MATHML => "MathML if possible (experimental)",
|
||||
);
|
||||
|
||||
/* private */ $wgDateFormatsEn = array(
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ $wgEditEncoding = "x";
|
|||
"HTMLigu se eble, aŭ PNG",
|
||||
"Lasu TeX-fonton (por tekstfoliumiloj)",
|
||||
"Rekomendita por modernaj foliumiloj",
|
||||
"MathML seeble (provizora)",
|
||||
);
|
||||
|
||||
/* private */ $wgUserTogglesEo = array(
|
||||
|
|
|
|||
Loading…
Reference in a new issue