mode to maintain valid XHTML, see // http://sourceforge.net/tracker/index.php?func=detail&aid=1201963&group_id=114997&atid=670231 $enclose = GESHI_HEADER_DIV; $geshi->enable_line_numbers( GESHI_FANCY_LINE_NUMBERS ); } // Starting line number if( isset( $args['start'] ) ) $geshi->start_line_numbers_at( $args['start'] ); $geshi->set_header_type( $enclose ); // Strict mode if( isset( $args['strict'] ) ) $geshi->enable_strict_mode(); // Format $out = $geshi->parse_code(); $err = $geshi->error(); if( $err ) { // Error! return self::formatError( $err ); } else { // Armour for Parser::doBlockLevels() if( $enclose == GESHI_HEADER_DIV ) $out = str_replace( "\n", '', $out ); // Register CSS $parser->mOutput->addHeadItem( self::buildHeadItem( $geshi ), "source-{$lang}" ); return '
' . $out . '
'; } } /** * Hook into Article::view() to provide syntax highlighting for * custom CSS and JavaScript pages * * @param string $text * @param Title $title * @param OutputPage $output * @return bool */ public static function viewHook( $text, $title, $output ) { // Determine the language preg_match( '!\.(css|js)$!u', $title->getText(), $matches ); $lang = $matches[1] == 'css' ? 'css' : 'javascript'; // Attempt to format $geshi = self::prepare( $text, $lang ); if( $geshi instanceof GeSHi ) { $out = $geshi->parse_code(); if( !$geshi->error() ) { // Done $output->addHeadItem( "source-$lang", self::buildHeadItem( $geshi ) ); $output->addHtml( "
{$out}
" ); return false; } } // Bottle out return true; } /** * Initialise a GeSHi object to format some code, performing * common setup for all our uses of it * * @param string $text * @param string $lang * @return GeSHi */ private static function prepare( $text, $lang ) { self::initialise(); $geshi = new GeSHi( $text, $lang ); if( $geshi->error() == GESHI_ERROR_NO_SUCH_LANG ) return null; $geshi->set_encoding( 'UTF-8' ); $geshi->enable_classes(); $geshi->set_overall_class( "source-$lang" ); $geshi->enable_keyword_links( false ); return $geshi; } /** * Prepare a CSS snippet suitable for use as a ParserOutput/OutputPage * head item * * @param GeSHi $geshi * @return string */ private static function buildHeadItem( $geshi ) { global $wgUseSiteCss, $wgSquidMaxage; $lang = $geshi->language; $css[] = ''; if( $wgUseSiteCss ) { $title = Title::makeTitle( NS_MEDIAWIKI, 'Geshi.css' ); $q = "usemsgcache=yes&action=raw&ctype=text/css&smaxage={$wgSquidMaxage}"; $css[] = ''; } return implode( "\n", $css ); } /** * Format an error message * * @param string $error * @return string */ private static function formatError( $error = '' ) { $html = ''; if( $error ) $html .= "

{$error}

"; $html .= '

' . htmlspecialchars( wfMsgForContent( 'syntaxhighlight-specify' ) ) . ' <source lang="html">...</source>

' . '

' . htmlspecialchars( wfMsgForContent( 'syntaxhighlight-supported' ) ) . '

' . self::formatLanguages(); return "
{$html}
"; } /** * Format the list of supported languages * * @return string */ private static function formatLanguages() { $langs = self::getSupportedLanguages(); $list = array(); if( count( $langs ) > 0 ) { foreach( $langs as $lang ) { $list[] = '' . htmlspecialchars( $lang ) . ''; } return '

' . implode( ', ', $list ) . '

'; } else { return '

' . htmlspecialchars( wfMsgForContent( 'syntaxhighlight-err-loading' ) ) . '

'; } } /** * Get the list of supported languages * * @return array */ private static function getSupportedLanguages() { if( !is_array( self::$languages ) ) { self::initialise(); self::$languages = array(); foreach( glob( GESHI_LANG_ROOT . "/*.php" ) as $file ) { self::$languages[] = basename( $file, '.php' ); } sort( self::$languages ); } return self::$languages; } /** * Initialise messages and ensure the GeSHi class is loaded */ private static function initialise() { if( !self::$initialised ) { wfLoadExtensionMessages( 'SyntaxHighlight_GeSHi' ); if( !class_exists( 'GeSHi' ) ) require( 'geshi/geshi.php' ); self::$initialised = true; } return true; } }