'LatexDoc', 'version' => '2008/03/09', 'author' => 'Austin Che', 'url' => 'http://openwetware.org/wiki/User:Austin_J._Che/Extensions/LatexDoc', 'description' => 'Write LaTeX documents on the wiki', ); class LatexDoc { var $latexmk; // full path to latexmk var $args; // args to latexmk var $workingDir; var $workingPath; function LatexDoc() { global $wgUploadDirectory, $wgUploadPath, $wgScriptPath, $IP; $this->latexmk = "$IP/extensions/latexmk"; $this->args = "-f -silent -pdf"; if ($wgUploadDirectory) $this->workingDir = "$wgUploadDirectory/latexdoc"; else $this->workingDir = "$IP/images/latexdoc"; if ($wgUploadPath) $this->workingPath = "$wgUploadPath/latexdoc"; else $this->workingPath = "$wgScriptPath/images/latexdoc"; } function onUnknownAction( $action, $article ) { global $wgOut, $wgRequest, $IP; // Respond only to latexdoc action if ( $action != 'latexdoc' ) { return true; } // Check for non-existent article if ( !$article || !( $text = $article->fetchContent() ) ) { $wgOut->addWikiText( wfMsg( 'latexdoc_no_text' ) ); return false; } // Check permissions if ( !$article->mTitle->userCanRead() ) { $wgOut->loginToUse(); return false; } $ext = $wgRequest->getText( 'ext' ); $wgOut->setArticleFlag( false ); $wgOut->setArticleRelated( true ); $wgOut->setRobotpolicy( 'noindex,nofollow' ); $wgOut->setPageTitle( $article->mTitle->getPrefixedText() ); // Get path if ( !is_dir( $this->workingDir ) ) { if ( !mkdir( $this->workingDir, 0777 ) ) { $wgOut->addWikiText( wfMsg( 'latexdoc_cant_create_dir', $this->workingDir ) ); return false; } } chdir( $this->workingDir ); $hash = md5( $text ); $filename = 'ltd_' . $hash; $fullpath = $this->workingDir . '/' . $filename; $url = $this->workingPath . '/' . $filename; if ( ! $wgRequest->getBool('cache', true) && file_exists( "$fullpath.$ext")) @unlink("$fullpath.$ext"); if ( ! file_exists( "$fullpath.$ext" ) ) { // need to generate/regenerate the output if ($this->getHelperFiles($text) && $this->runLatex( $text, $filename )) { $wgOut->redirect( "$url.$ext" ); } // else it failed } else $wgOut->redirect( "$url.$ext" ); chdir( $IP ); return false; } function getHelperFiles($text) { global $wgOut; // search for \usewikifile{..} preg_match_all("/\\\\usewikifile{(.*)}{(.*)}/", $text, $matches, PREG_SET_ORDER); foreach ($matches as $val) { $page = $val[1]; $outfile = $val[2]; if (preg_match("/[^-\w.]/", $outfile) || preg_match("/^[.]/", $outfile)) { $wgOut->addWikiText(wfMsg('latexdoc_invalid_filename', $outfile)); return false; } $title = Title::newFromText($page); if ($title) { if ($title->getNamespace() == NS_IMAGE) { $localFile = wfLocalFile($title); if (! $localFile->exists()) { $wgOut->addWikiText(wfMsg('latexdoc_no_page', $page)); return false; } if (! copy ($localFile->getPath(), $outfile)) { $wgOut->addWikiText( wfMsg( 'latexdoc_cant_write', "$outfile" ) ); return false; } continue; } $rev = Revision::newFromTitle($title); } if (!$title || ! $rev) { $wgOut->addWikiText(wfMsg('latexdoc_no_page', $page)); return false; } else { $inFile = fopen( $this->workingDir . '/' . $outfile, 'w' ); if ( !$inFile ) { $wgOut->addWikiText( wfMsg( 'latexdoc_cant_write', "$outfile" ) ); return false; } fwrite( $inFile, $rev->getText()); fclose( $inFile ); } } return true; } function runLatex( $text, $file ) { global $wgOut, $wgRequest; // remove all \usewikifile commands $text = preg_replace("/\\\\usewikifile{.*}{.*}/", "", $text); // Write input file $inFile = fopen( "$file.tex", 'w' ); if ( !$inFile ) { $wgOut->addWikiText( wfMsg( 'latexdoc_cant_write', "$file.tex" ) ); return false; } fwrite( $inFile, $text ); fclose( $inFile ); // Run LaTeX $cmd = $this->latexmk . " $this->args " . wfEscapeShellArg( "$file" ) . " 2>&1"; exec($cmd, $output, $error); // Report errors // we currently use -f with latexmk so that no exit code is returned // as we need to distinguish between undefined references (which we still consider success) // and genuine latex errors foreach ($output as $outputline) { if (preg_match("/^====.*error.*====$/", $outputline)) { // this is an erorr // could have partially generated pdf, delete it (some browsers will crash) @unlink("$file.pdf" ); wfSuppressWarnings(); $log = '
' . file_get_contents( "$file.log" ) . '
'; wfRestoreWarnings(); $wgOut->addWikiText( wfMsg( 'latexdoc_error', $log ) ); return false; } } return true; // Delete temporary files //@unlink( "$file.tex" ); //@unlink( "$file.aux" ); //@unlink( "$file.log" ); } function onParserBeforeStrip( &$parser, &$text, &$stripState ) { // If the article looks vaguely like TeX, render it with syntax highlighting (if available) // with a link for pdf generation global $wgSyntaxHighlight; if ( strpos( $text, '\begin{document}' ) !== false ) { $sk =& $parser->mOptions->getSkin(); $links = $sk->makeKnownLinkObj( $parser->mTitle, wfMsg( 'latexdoc_get_pdf' ), 'action=latexdoc&ext=pdf' ) . " | " . $sk->makeKnownLinkObj( $parser->mTitle, wfMsg( 'latexdoc_get_log' ), 'action=latexdoc&ext=log' ) . " | " . $sk->makeKnownLinkObj( $parser->mTitle, wfMsg( 'latexdoc_get_pdf_no_cache' ), 'action=latexdoc&ext=pdf&cache=0' ) . " | " . $sk->makeKnownLinkObj( $parser->mTitle, wfMsg( 'latexdoc_get_source' ), 'action=raw&ctype=application/x-tex&filename=wiki_latex_source.tex' ); $links = $parser->insertStripItem($links, $stripState); // make list of included files preg_match_all("/\\\\usewikifile{(.*)}{(.*)}/", $text, $matches, PREG_SET_ORDER); $files = '
'; $files = $files . 'Included files:'; foreach ($matches as $val) { $files = $files . "\n*[[:" . $val[1] . "]]"; } $files = $files . '
'; $text = wordwrap($text); if ($wgSyntaxHighlight) $text = $wgSyntaxHighlight->highlight($text, "latex"); else $text = "
$text
"; // no syntax highlighting $text = $parser->insertStripItem($text, $stripState); $text = "$links
$files

$text"; } return true; } // Needed in some versions to prevent Special:Version from breaking function __toString() { return 'LatexDoc'; } } $wgLatexDoc = new LatexDoc; function wfLatexDocInit() { global $wgHooks, $wgLatexDoc, $wgMessageCache; $wgHooks['UnknownAction'][] = &$wgLatexDoc; $wgHooks['ParserBeforeStrip'][] = &$wgLatexDoc; $wgMessageCache->addMessages( array( 'latexdoc_invalid_filename' => 'Filename $1 is invalid', 'latexdoc_no_page' => 'Wiki page $1 does not exist', 'latexdoc_no_text' => 'Article contains no text, cannot generate output', 'latexdoc_cant_create_dir' => 'Cannot create temporary directory $1', 'latexdoc_cant_write' => 'Cannot write to file $1', 'latexdoc_error' => "LaTeX error:
\n\n$1", 'latexdoc_get_pdf' => 'Get PDF', 'latexdoc_get_log' => 'Get log', 'latexdoc_get_pdf_no_cache' => 'Regenerate PDF', 'latexdoc_get_source' => 'Export Source', )); } ?>