Solution de WikiMedia
En s'inspirant
beaucoup de mediawiki, le moteur de
WikiPedia, on peut supporter simplement les formules TeX. Suivant que la formule est simple (i_2) ou compliquée (\sum_i...), le rendu se fera en HTML directement, ou sous la forme d'une image png (installation LaTeX requise côté serveur). J'ai repris mediawiki dans wikini pour supporter ce genre d'écritures : \( i_2 \), et \[ i_2 \]. Le premier est associé à une classe CSS "math_inline", le second "math_center", pour pouvoir émuler la mise en page LaTeX. Dernier détail : il y a un mécanisme de cache pour stocker les images/codes html générés pour accélérer le chargement des pages.
Marche à suivre :
- avoir installé wikini, LaTeX, ghostcript sur le serveur wikini.
- sur le serveur ou toute autre machine où Objective Caml est installé, récupérer le répertoire "math" du cvs de mediawiki (http://cvs.sourceforge.net/viewcvs.py/wikipedia/phase3/math/). Le compiler (make), ce qui générera 3 binaires, dont texvc. texvc est le moteur de rendu TeX -> HTML ou MathML en Caml. Le README explique le format qu'il sort.
- mettre le binaire texvc dans formatters/ du wikini sur le serveur.
- mettre le script suivant dans formatters/ de wikini et l'appeler math.php (repris quasiment texto du script includes/Math.php de mediawiki).
<?
/*
* Almost entirely taken from mediawiki :
* http://cvs.sourceforge.net/viewcvs.py/wikipedia/phase3/includes/
*/
if (!function_exists("wfEscapeHTML"))
{
function wfEscapeHTML( $in )
{
return str_replace(
array( "&", "\"", ">", "<" ),
array( "&", """, ">", "<" ),
$in );
}
}
if (!function_exists("linkToMathImage"))
{
function linkToMathImage ($wgMathPath, $tex, $outputhash )
{
global $wiki;
return "<img src=\"".$wgMathPath."/"
.$outputhash.$wiki->config["ghostscript_png_ext"]
."\" alt=\"".wfEscapeHTML($tex)."\">";
}
}
if (!function_exists("renderMath"))
{
function renderMath( $tex )
{
global $wiki;
$mf = "math_failure";
$munk = "math_unknown_error";
$math_dir_url = $wiki->config["math_dir_url"];
$math_dir_sys = $wiki->config["math_dir_sys"];
$math_tmp_dir = $wiki->config["math_tmp_dir"];
$math_inputenc = $wiki->config["math_inputenc"];
$math_render_type = $wiki->config["math_render_type"];
/* 0 : "Toujours produire une image PNG",
1 : "HTML si tres simple, autrement PNG",
2 : "HTML si possible, autrement PNG",
3 : "Laisser le code ""TeX"" original",
4 : "Pour les navigateurs modernes" (mathml) */
if ($math_render_type == 3)
return ('$ '.wfEscapeHTML($tex).' $');
$md5 = md5($tex);
$md5_sql = mysql_escape_string(pack("H32", $md5));
if ($math_render_type == 0)
$sql = "SELECT math_outputhash FROM ".$wiki->config["table_prefix"]
."math WHERE math_inputhash = '".$md5_sql."'";
else
$sql = "SELECT math_outputhash,math_html_conservativeness,math_html FROM ".$wiki->config["table_prefix"]."math WHERE math_inputhash = '".$md5_sql."'";
$res = $wiki->Query($sql);
if( $rpage = mysql_fetch_object( $res ) ) {
$outputhash = unpack( "H32md5",
$rpage->math_outputhash
. " " );
$outputhash = $outputhash ['md5'];
if( file_exists( "$math_dir_sys/$outputhash"
.$wiki->config["ghostscript_png_ext"] ) )
{
if (($math_render_type == 0)
|| ($rpage->math_html == '')
|| (($math_render_type == 1)
&& ($rpage->math_html_conservativeness != 2))
|| (($math_render_type == 4)
&& ($rpage->math_html_conservativeness == 0)))
return linkToMathImage ( $wiki->config["math_dir_url"],
$tex, $outputhash );
else
{
return $rpage->math_html;
}
}
}
$cmd = $wiki->config["math_texvc_path"]." "
.escapeshellarg($math_tmp_dir)." "
.escapeshellarg($math_dir_sys)." "
.escapeshellarg($tex)." ".escapeshellarg($math_inputenc);
echo $cmd;
$contents = `$cmd`;
if (strlen($contents) == 0)
return "<b>".$mf." (".$munk." 1): ".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." ".$retval;
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." 3): ".wfEscapeHTML($tex)."</b>";
$outmd5_sql = mysql_escape_string(pack("H32", $outmd5));
$sql = "REPLACE INTO ".$wiki->config["table_prefix"]."math VALUES ('"
.$md5_sql."', '".$outmd5_sql."', ".$conservativeness.", ".$sql_html
.", ".$sql_mathml.")";
$res = $wiki->Query($sql);
# we don't really care if it fails
if (($math_render_type == 0) || ($rpage->math_html == '')
|| (($math_render_type == 1) && ($conservativeness != 2))
|| (($math_render_type == 4) && ($conservativeness == 0)))
return linkToMathImage($wiki->config["math_dir_url"],
$tex, $outmd5);
else
return $outhtml;
}
}
echo renderMath($text);
?>
- Rajouter un répertoire math_img accessible en écriture par le serveur http, par exemple à la racine de wikini.
- Pour personnaliser la config, rajouter dans le wakka.config.php (en l'incluant dans la fonction array);
/* Chemin HTTP pour math_img */
"math_dir_url" => "/wikini/math_img",
/* Chemin système pour math_img */
"math_dir_sys" => "/var/httpd/htdocs/wikini/math_img",
/* Chemin système vers l'exécutable texvc */
"math_texvc_path" => "/var/httpd/htdocs/wikini/formatters/texvc",
/* Répertoire système pour les fichiers temporaires */
"math_tmp_dir" => "/tmp",
"math_inputenc" => "UTF-8",
"math_render_type" => "1",
/* Valeurs possibles pour math_render_type :
0 : "Toujours produire une image PNG",
1 : "HTML si tres simple, autrement PNG",
2 : "HTML si possible, autrement PNG",
3 : "Laisser le code TeX original",
4 : "Pour les navigateurs modernes" (mathml) */
"ghostscript_png_ext" => ".png",
/* Valeurs possibles pour ghostscript_png_ext :
Versions anciennes de ghostscript : ".png.0"
Versions récentes de ghostscript : ".png" */
- Modifier le script formatters/wakka.php du wikini :
@@ -117,6 +119,26 @@
{
return $matches[1];
}
+ // \(math\)
+ else if (preg_match("/^[\\\\]\\((.*)[\\\\]\\)$/s",
+ $thing, $matches))
+ {
+ $output = "<div class=\"math_inline\">";
+ $output .= $wiki->Format(trim($matches[1]), "math");
+ $output .= "</div>";
+
+ return $output;
+ }
+ // \[math\]
+ else if (preg_match("/^[\\\\]\\[(.*)[\\\\]\\]$/s",
+ $thing, $matches))
+ {
+ $output = "<div class=\"math_center\">";
+ $output .= $wiki->Format(trim($matches[1]), "math");
+ $output .= "</div>";
+
+ return $output;
+ }
// code text
else if (preg_match("/^\%\%(.*)\%\%$/s", $thing, $matches))
{
@@ -278,6 +300,8 @@
$text = trim($text)."\n";
$text = preg_replace_callback(
"/(\%\%.*?\%\%|".
+ "[\\\\]\\[.*?[\\\\]\\]|".
+ "[\\\\]\\(.*?[\\\\]\\)|".
"\"\".*?\"\"|".
"\[\[.*?\]\]|".
"\b[a-z]+:\/\/\S+|".
- créer la table wikini_math suivante dans la base wikini sur mysql. Elle permet de maintenir en cache la liste des images déjà générées pour accélérer le chargement d'une parge :
- Dans le wakka.css rajouter le nécessaire pour la mise en page des deux types de formules maths :
div.math_inline { display: inline; }
div.math_center { text-align: center; }
Et voilà.
--
DavidDecotigny
Salut,
ça serait vraiment bien si on n'avais pas besoin d'installer
LaTeX, Ghostscript... sur le serveur
Peut-être existe-il un serveur permettant de générer les images ?
--
SebCls?