====== TeX ====== This patch (to 2005-05-07 version) add AMSLaTeX mathematical expresion support to Dokuwiki. http://smp.if.uj.edu.pl/wiki/tex.diff diff -ruN ./wiki.org/inc/mediawiki/Math.php ./wiki/inc/mediawiki/Math.php --- ./wiki.org/inc/mediawiki/Math.php1970-01-01 01:00:00.000000000 +0100 +++ ./wiki/inc/mediawiki/Math.php2005-05-13 08:55:34.000000000 +0200 @@ -0,0 +1,230 @@ + parsing + * @package MediaWiki + */ + +/** + * 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) + * + * @package MediaWiki + */ +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; +} + +function render() { +global $wgMathDirectory, $wgTmpDirectory, $wgInputEncoding; +global $wgTexvc; +$fname = 'MathRenderer::render'; + +if( $this->mode == MW_MATH_SOURCE ) { +# No need to render or parse anything more! +return ('$ '.htmlspecialchars( $this->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); +} 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; +$this->mathml = NULL; +} else if ($retval == 'X') { +$this->html = NULL; +$this->mathml = substr ($contents, 33); +$this->conservativeness = 0; +} else if ($retval == '+') { +$this->html = NULL; +$this->mathml = NULL; +$this->conservativeness = 0; +} else { +$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: +if ( !wfReadOnly() ) { +$outmd5_sql = pack('H32', $this->hash); + +$md5_sql = pack('H32', $this->md5); # Binary packed, not hex + +$dbw =& wfGetDB( DB_MASTER ); +$dbw->replace( 'math', array( 'math_inputhash' ), + array( +'math_inputhash' => $md5_sql, +'math_outputhash' => $outmd5_sql, +'math_html_conservativeness' => $this->conservativeness, +'math_html' => $this->html, +'math_mathml' => $this->mathml, + ), $fname, array( 'IGNORE' ) +); +} +*/ +} + +return $this->_doRender(); +} + +function _error( $msg, $append = '' ) { +$mf = htmlspecialchars( 'math_failure' ); +$munk = htmlspecialchars( 'math_unknown_error' ); +$errmsg = htmlspecialchars( $msg ); +$source = htmlspecialchars($this->tex); +return "$mf ($errmsg$append): $source\n"; +} + +function _recall() { +global $wgMathDirectory; +$fname = 'MathRenderer::_recall'; + +$this->md5 = md5( $this->tex ); +/*$dbr =& wfGetDB( DB_SLAVE ); +$rpage = $dbr->selectRow( 'math', +array( 'math_outputhash','math_html_conservativeness','math_html','math_mathml' ), +array( 'math_inputhash' => pack("H32", $this->md5)), # Binary packed, not hex +$fname +); +*/ + +if( $rpage !== false ) { +# 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; +} + +/** + * Select among PNG, HTML, or MathML output depending on + */ +function _doRender() { +if( $this->mode == MW_MATH_MATHML && $this->mathml != '' ) { +return "{$this->mathml}"; +} +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.''; +};echo "aaa"; +} + +function _linkToMathImage() { +global $wgMathPath; +$url = htmlspecialchars( "$wgMathPath/{$this->hash}.png" ); +$alt = trim(str_replace("\n", ' ', htmlspecialchars( $this->tex ))); +return "\"$alt\""; +} +} + +function renderMath( $tex ) { +//global $wgUser; +$math = new MathRenderer( $tex ); +//$math->setOutputMode( $wgUser->getOption('math')); +$math->setOutputMode( MW_MATH_PNG ); +return $math->render(); +} + +?> diff -ruN ./wiki.org/inc/parser/handler.php ./wiki/inc/parser/handler.php --- ./wiki.org/inc/parser/handler.php2005-05-07 11:22:56.000000000 +0200 +++ ./wiki/inc/parser/handler.php2005-05-15 06:55:00.000000000 +0200 @@ -510,6 +510,17 @@ } return TRUE; } + + function math($match, $state, $pos) { + switch ( $state ) { + case DOKU_LEXER_UNMATCHED: + $this->_addCall('append', array(renderMath($match)), $pos); + break; + } + return TRUE; + + return TRUE; + } } //------------------------------------------------------------------------ diff -ruN ./wiki.org/inc/parser/parser.php ./wiki/inc/parser/parser.php --- ./wiki.org/inc/parser/parser.php2005-05-07 11:22:56.000000000 +0200 +++ ./wiki/inc/parser/parser.php2005-05-15 06:51:10.000000000 +0200 @@ -335,6 +335,7 @@ $this->allowedModes[] = 'php'; $this->allowedModes[] = 'code'; $this->allowedModes[] = 'file'; + $this->allowedModes[] = 'html'; } function connectTo($mode) { @@ -837,6 +838,7 @@ $modes = array( 'preformatted','code','file', 'php','html','quote', +'math', ); return $modes; } @@ -849,5 +851,16 @@ return $modes; } +class Doku_Parser_Mode_Math extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addEntryPattern('(?=.*)',$mode,'math'); + } + + function postConnect() { + $this->Lexer->addExitPattern('','math'); + } +} + //Setup VIM: ex: et ts=4 enc=utf-8 : diff -ruN ./wiki.org/inc/parser/xhtml.php ./wiki/inc/parser/xhtml.php --- ./wiki.org/inc/parser/xhtml.php2005-05-07 11:22:56.000000000 +0200 +++ ./wiki/inc/parser/xhtml.php2005-05-13 08:56:13.000000000 +0200 @@ -724,6 +724,11 @@ $this->doc .= $this->_formatLink($link); } + function append ($str) { + $this->doc .= $str; + } + + /** * Renders an RSS feed using Magpie * diff -ruN ./wiki.org/inc/parserutils.php ./wiki/inc/parserutils.php --- ./wiki.org/inc/parserutils.php2005-05-07 11:22:56.000000000 +0200 +++ ./wiki/inc/parserutils.php2005-05-13 08:34:57.000000000 +0200 @@ -11,6 +11,8 @@ require_once(DOKU_INC.'inc/confutils.php'); require_once(DOKU_INC.'inc/pageutils.php'); + require_once(DOKU_INC.'inc/mediawiki/Math.php'); + /** * Returns the parsed Wikitext in XHTML for the given id and revision. @@ -210,7 +212,9 @@ $Parser->addMode('windowssharelink',new Doku_Parser_Mode_WindowsShareLink()); //$Parser->addMode('filelink',new Doku_Parser_Mode_FileLink()); //FIXME ??? $Parser->addMode('eol',new Doku_Parser_Mode_Eol()); - + + $Parser->addMode('math',new Doku_Parser_Mode_Math()); + // Do the parsing $p = $Parser->parse($text); # dbg($p); \\ Apply this patch in main dokuwiki directory with ''patch -p1 < abovepatch.diff'' \\ You will also need latex, tetex, dvipng, imagemagic, ghostscript, ocaml (''apt-get install dvipng latex convert gs ocaml'' on Debian) and texvc. Get texvc (get from Mediawiki main distrbution file or SF project page http://sourceforge.net/project/showfiles.php?group_id=34373&package_id=111620 http://sourceforge.net/project/showfiles.php?group_id=34373). \\ Install everything, compile texvc and place someware. Change a very beging of ./wiki/inc/mediawiki/Math.php file. \\ Mathematical mode is accessible by '' '' tag. Only mathematical mode is avaible but it's very fast and cache results. \\ \\ Example: \frac{\sum_{n=1}^N x^{\sqrt{n+1}}-x^{x^{2n}}}{(\ln(x)+2x^{4x+1289})^{\frac{1}{2}}} Result: {{http://smp.if.uj.edu.pl/wiki/mathimg/a8796456bc988db0c8fea32c22734b2b.png}} You can configure it to produce MathML, PNG, HTML. ---- 15 May 2005, Witold Baryluk