posts - 81, comments - 262, trackbacks - 0

MediaWiki Math Extension with texvc on Windows with Cygwin


Adding the math extension to MediaWiki requires compiling texvc. On my Windows box I chose to use Cygwin to compile texvc, since it's easily compiled with make and the GNU toolchain.

Building with Cygwin

First, make sure you have the necessary dependencies installed within Cygwin (http://cygwin.com/install.html).

  • Make, latex, ocaml, etc.

To compile navigate with Cygwin's shell to the source directory of the math extension (recalling windows paths are in \cygdrive\[driveletter])

~/Extensions/Math/math

Then compile by calling make

$ make

Finally, be sure to add the Cygwin binaries to your PATH variable if they aren't already so that the binary will run.

The textvc.exe binary is now compiled, but some customizations were needed beyond the normal install.

 

Updating the extension

I used Microsoft's Web Installer to install MediaWiki 1.20, the following customizations where used to setup the Math Extensions using a snapshot from 8/27/2012. During the install I found this section of the MediaWiki very useful: http://www.mediawiki.org/wiki/Manual:Running_MediaWiki_on_Windows#Building_texvc_on_Windows

 

The important change in using Cygwin's build of texvc is to pass relative paths to the temp and output directories. Other changes are largely patchwork to account form install the development branch of the Math Extension into MediaWiki 1.20.

 

LocalSettings.php changes

Add the following settings to LocalSettings.php

# Math extensions
require_once("$IP/extensions/Math/Math.php");
$wgUseTeX = true;
$wgTexvc = 'texvc.exe';
$wgMathPath = '{$wgUploadPath}/math';
$wgMathDirectory = 'images/math';
$wgTmpDirectory = 'images/temp';
$wgMathPath = 'images/math';

 

 

Math.body.php changes

A set of changes are needed to skip the use of Cygwin's Shell, use the relative paths, fix a quoting bug, and skip some of the new file store development.

 

Fix an issue with wrapping the TeX code. Using single quotes was found to render incorrect TeX

    function wfEscapeSingleQuotes( $str ) {
        // fix a rendering bug with TeX that occurs when wraping the TeX in single
        // quotes instead of double quotes

        return "\"" . trim(str_replace( "'", "'\\''", $str )) . "\"";
    }

 

Expose the new settings in LocalSettings.php to render

    // expose the temp and math directory configurations
    function render() {
        global $wgTexvc, $wgTexvcBackgroundColor, $wgUseSquid, $wgTmpDirectory, $wgMathDirectory;

 

Several updates to the execution of TeX.

        // Don't use the system's temp directory
        //$wgTmpDirectory = wfTempDir();

        if( !$this->_recall() ) { // cache miss
            // skip this check since $wgTexvc is retooled as a path to the
            // executable
            /*if( !is_executable( $wgTexvc ) ) {
                return $this->_error( 'math_notexvc' );
            }*/


            // Use the temp and math directories as desired

            $cmd = $wgTexvc . ' ' .
                wfEscapeSingleQuotes( $wgTmpDirectory ) . ' '.
                wfEscapeSingleQuotes( $wgMathDirectory ) . ' '.
                wfEscapeSingleQuotes( $this->tex ) . ' '.
                wfEscapeSingleQuotes( 'UTF-8' ) . ' '.
                wfEscapeSingleQuotes( $wgTexvcBackgroundColor );

            if ( wfIsWindows() ) {
                # Invoke it within cygwin sh, because texvc expects sh features in its default shell
                    #$cmd = 'sh -c ' . wfEscapeShellArg( $cmd );

                // Shell isn't necessary, so skip it. First change directory to
                // the binary, then call texvc.exe with relative paths to
                // the math and temp directories (necessary for the sub-call
                // to imagemagic)

                    $cmd = 'cd extensions/Math/math && ' . $wgTexvc . ' '.
                wfEscapeSingleQuotes( '../../../' . $wgTmpDirectory ) . ' '.
                wfEscapeSingleQuotes( '../../../' . $wgMathDirectory ) . ' '.
                wfEscapeSingleQuotes( str_replace("\n"," ",$this->tex )) . ' '.
                wfEscapeSingleQuotes( 'iso-8859-1' ) . ' '.
                wfEscapeSingleQuotes( $wgTexvcBackgroundColor ) .
                '';

            }
        


            wfDebug( "TeX: $cmd\n" );
            $contents = wfShellExec( $cmd );
            wfDebug( "TeX output:\n $contents\n---\n" );
                        

            if ( strlen( $contents ) == 0 ) {
                // correct the temp directory used
                if ( !file_exists( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) {
                    return $this->_error( 'math_bad_tmpdir' );
                } else {
                    return $this->_error( 'math_unknown_error' );
                }
            }

            // update the temp file (deletes on release)
            $tempFsFile = new TempFSFile( realpath("$wgMathDirectory/{$this->hash}.png") );
            
            // autocollect() is not available in the mediawiki version used
            //$tempFsFile->autocollect(); // destroy file when $tempFsFile leaves scope

            



            // use realpath to get the full path from the relative paths
            if ( $errmsg ) {
                return $errmsg;
            } elseif ( !preg_match( "/^[a-f0-9]{32}$/", $this->hash ) ) {
                return $this->_error( 'math_unknown_error' );
            } elseif( !file_exists( realpath("$wgMathDirectory/{$this->hash}.png") ) ) {
                return $this->_error( 'math_image_error' );
            } elseif( filesize( realpath("$wgMathDirectory/{$this->hash}.png" ) ) == 0 ) {
                return $this->_error( 'math_image_error' );


            // the backend features used here are not yet in mediawiki
/*

            $hashpath = $this->_getHashPath(); // final storage directory

            $backend = $this->getBackend();
            # Create any containers/directories as needed...
            if ( !$backend->prepare( array( 'dir' => $hashpath ) )->isOK() ) {
                return $this->_error( 'math_output_error' . 'test ' );
            }
            // Store the file at the final storage path...
            if ( !$backend->quickStore( array(
                'src' => "$wgTmpDirectory/{$this->hash}.png", 'dst' => "$hashpath/{$this->hash}.png"
                ) )->isOK()
            ) {
                return $this->_error( 'math_output_error' );
            }*/

Path corrections to remove the new backend use

    function _mathImageUrl() {
        global $wgMathPath;
        $dir = $this->_getHashSubPath();
        
        // use the path (uri) to the math directory
        return "$wgMathPath/{$this->hash}.png";
    }

    /**
     * @return string Storage directory
     */

    function _getHashPath() {
        // skip the backend work
        $path = 'images' . //$this->getBackend()->getRootStoragePath() .
            '/math-render/' . $this->_getHashSubPath();
        wfDebug( "TeX: getHashPath, hash is: $this->hash, path is: $path\n" );
        return $path;
    }




Print | posted on Monday, August 27, 2012 11:09 PM |

Powered by:
Powered By Subtext Powered By ASP.NET