r23538 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r23537‎ | r23538 | r23539 >
Date:04:33, 29 June 2007
Author:robchurch
Status:old
Tags:
Comment:
* Massive refactor; move a lot of code out of the global function namespace and clean several bits up, including broken use of $wgUser inside parser hook
* Take advantage of the new "ShowRawCssJs" hook and format CSS and JavaScript when viewing those pages
Modified paths:
  • /trunk/extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.class.php (added) (history)
  • /trunk/extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.i18n.php (modified) (history)
  • /trunk/extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.i18n.php
@@ -13,7 +13,7 @@
1414 'en' => array(
1515 'syntaxhighlight-specify' => 'You need to specify a language like this:',
1616 'syntaxhighlight-supported' => 'Supported languages for syntax highlighting:',
17 -'syntaxhighlight-err-loading' => '(error loading support language list)',
 17+'syntaxhighlight-err-loading' => '(error loading supported language list)',
1818 'syntaxhighlight-err-language' => 'Invalid language.',
1919 'geshi.css' => '/* CSS placed here will be applied to GeSHi syntax highlighting */',
2020 ),
Index: trunk/extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.php
@@ -41,164 +41,21 @@
4242 if( !defined( 'MEDIAWIKI' ) )
4343 die();
4444
45 -$wgExtensionFunctions[] = 'syntaxHighlightSetup';
4645 $wgExtensionCredits['parserhook']['SyntaxHighlight_GeSHi'] = array(
4746 'name' => 'SyntaxHighlight',
48 - 'author' => 'Brion Vibber',
 47+ 'author' => array( 'Brion Vibber', 'Tim Starling', 'Rob Church' ),
4948 'description' => 'Provides syntax highlighting using [http://qbnz.com/highlighter/ GeSHi Highlighter]',
5049 'url' => 'http://www.mediawiki.org/wiki/Extension:SyntaxHighlight_GeSHi',
5150 );
52 -$wgHooks['LoadAllMessages'][] = 'syntaxHighlightLoadMessages';
5351
54 -function syntaxHighlightSetup() {
55 - global $wgParser;
56 - $wgParser->setHook( 'source', 'syntaxHighlightHook' );
57 -}
 52+$wgAutoloadClasses['SyntaxHighlight_GeSHi'] = dirname( __FILE__ ) . '/SyntaxHighlight_GeSHi.class.php';
 53+$wgHooks['ShowRawCssJs'][] = 'SyntaxHighlight_GeSHi::viewHook';//array( 'SyntaxHighlight_GeSHi', 'viewHook' );
 54+$wgExtensionFunctions[] = 'efSyntaxHighlight_GeSHiSetup';
5855
59 -function syntaxHighlightLoadMessages() {
60 - static $loaded = false;
61 - if ( $loaded ) {
62 - return true;
63 - }
64 - global $wgMessageCache;
65 - require_once( dirname( __FILE__ ) . '/SyntaxHighlight_GeSHi.i18n.php' );
66 - foreach( efSyntaxHighlight_GeSHiMessages() as $lang => $messages )
67 - $wgMessageCache->addMessages( $messages, $lang );
68 - return true;
69 -}
70 -
71 -function syntaxHighlightHook( $text, $params = array(), $parser ) {
72 - if ( !class_exists( 'GeSHi' ) ) {
73 - require( 'geshi/geshi.php' );
74 - }
75 - syntaxHighlightLoadMessages();
76 - return isset( $params['lang'] )
77 - ? syntaxHighlightFormat( trim( $text ), $params, $parser )
78 - : syntaxHighlightHelp();
79 -}
80 -
81 -function syntaxHighlightFormat( $text, $params, $parser ) {
82 - $lang = $params['lang'];
83 - if ( !preg_match( '/^[A-Za-z_0-9-]*$/', $lang ) ) {
84 - return syntaxHighlightHelp( wfMsgHtml( 'syntaxhighlight-err-language' ) );
85 - }
86 -
87 - $geshi = new GeSHi( $text, $lang );
88 - if ( $geshi->error == GESHI_ERROR_NO_SUCH_LANG ) {
89 - return syntaxHighlightHelp( wfMsgHtml( 'syntaxhighlight-err-language' ) );
90 - }
91 -
92 - $geshi->set_encoding( 'UTF-8' );
93 - $geshi->enable_classes();
94 - $geshi->set_overall_class( "source source-$lang" );
95 - $geshi->enable_keyword_links(false);
96 -
97 - if ( isset( $params['enclose'] ) && $params['enclose'] == 'div' ) {
98 - $enclose = GESHI_HEADER_DIV;
99 - } else {
100 - $enclose = GESHI_HEADER_PRE;
101 - }
102 -
103 - if ( isset( $params['line'] ) ) {
104 - // Pre mode with line numbers generates invalid HTML, need div mode
105 - // http://sourceforge.net/tracker/index.php?func=detail&aid=1201963&group_id=114997&atid=670231
106 - $enclose = GESHI_HEADER_DIV;
107 - $geshi->enable_line_numbers( GESHI_FANCY_LINE_NUMBERS );
108 - }
109 - if ( isset( $params['start'] ) ) {
110 - $geshi->start_line_numbers_at( $params['start'] );
111 - }
112 - $geshi->set_header_type( $enclose );
113 -
114 - if ( isset( $params['strict'] ) ) {
115 - $geshi->enable_strict_mode();
116 - }
117 -
118 - $out = $geshi->parse_code();
119 - $error = $geshi->error();
120 -
121 - if ( $error ) {
122 - return syntaxHighlightHelp( $error );
123 - } else {
124 - // Armour for doBlockLevels
125 - if ( $enclose == GESHI_HEADER_DIV ) {
126 - $out = str_replace( "\n", '', $out );
127 - }
128 -
129 - // Per-language class for stylesheet
130 - $geshi->set_overall_class( "source-$lang" );
131 -
132 - // Enable [[MediaWiki:Geshi.css]] (bug #9951)
133 - $sitecss = '';
134 - global $wgUseSiteCss;
135 - if( $wgUseSiteCss ) {
136 - global $wgUser, $wgSquidMaxage ;
137 - $query = "usemsgcache=yes&action=raw&ctype=text/css&smaxage=$wgSquidMaxage";
138 - $sk = $wgUser->getSkin();
139 - $sitecss =
140 - "<style type=\"text/css\">/*<![CDATA[*/\n" .
141 - '@import "' . $sk->makeNSUrl( 'Geshi.css', $query, NS_MEDIAWIKI ) . "\";\n" .
142 - "/*]]>*/</style>\n" ;
143 - }
144 -
145 - $parser->mOutput->addHeadItem(
146 - "<style type=\"text/css\">/*<![CDATA[*/\n" .
147 - ".source-$lang {line-height: normal;}\n" .
148 - ".source-$lang li {line-height: normal;}\n" .
149 - $geshi->get_stylesheet( false ) .
150 - "/*]]>*/</style>\n$sitecss",
151 - "source-$lang" );
152 - return $out;
153 - }
154 -}
155 -
15656 /**
157 - * Return a syntax help message
158 - * @param string $error HTML error message
 57+ * Register parser hook
15958 */
160 -function syntaxHighlightHelp( $error = false ) {
161 - return syntaxHighlightError(
162 - ( $error ? "<p>$error</p>" : '' ) .
163 - '<p>' . wfMsg( 'syntaxhighlight-specify' ) . ' ' .
164 - '<samp>&lt;source lang=&quot;html&quot;&gt;...&lt;/source&gt;</samp></p>' .
165 - '<p>' . wfMsg( 'syntaxhighlight-supported' ) . '</p>' .
166 - syntaxHighlightFormatList( syntaxHighlightLanguageList() ) );
167 -}
168 -
169 -/**
170 - * Put a red-bordered div around an HTML message
171 - * @param string $contents HTML error message
172 - * @return HTML
173 - */
174 -function syntaxHighlightError( $contents ) {
175 - return "<div style=\"border:solid red 1px; padding:.5em;\">$contents</div>";
176 -}
177 -
178 -function syntaxHighlightFormatList( $list ) {
179 - return empty( $list )
180 - ? wfMsg( 'syntaxhighlight-err-loading' )
181 - : '<p style="padding:0em 1em;">' .
182 - implode( ', ', array_map( 'syntaxHighlightListItem', $list ) ) .
183 - '</p>';
184 -}
185 -
186 -function syntaxHighlightListItem( $item ) {
187 - return "<samp>" . htmlspecialchars( $item ) . "</samp>";
188 -}
189 -
190 -function syntaxHighlightLanguageList() {
191 - $langs = array();
192 - $langroot = @opendir( GESHI_LANG_ROOT );
193 - if( $langroot ) {
194 - while( $item = readdir( $langroot ) ) {
195 - if( preg_match( '/^(.*)\\.php$/', $item, $matches ) ) {
196 - $langs[] = $matches[1];
197 - }
198 - }
199 - closedir( $langroot );
200 - }
201 - sort( $langs );
202 - return $langs;
203 -}
204 -
205 -
 59+function efSyntaxHighlight_GeSHiSetup() {
 60+ global $wgParser;
 61+ $wgParser->setHook( 'source', array( 'SyntaxHighlight_GeSHi', 'parserHook' ) );
 62+}
\ No newline at end of file
Index: trunk/extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.class.php
@@ -0,0 +1,208 @@
 2+<?php
 3+
 4+class SyntaxHighlight_GeSHi {
 5+
 6+ /**
 7+ * Has GeSHi been initialised this session?
 8+ */
 9+ private static $initialised = false;
 10+
 11+ /**
 12+ * List of languages available to GeSHi
 13+ */
 14+ private static $languages = null;
 15+
 16+ /**
 17+ * Parser hook
 18+ *
 19+ * @param string $text
 20+ * @param array $args
 21+ * @param Parser $parser
 22+ * @return string
 23+ */
 24+ public static function parserHook( $text, $args = array(), $parser ) {
 25+ self::initialise();
 26+ $text = trim( $text );
 27+ // Validate language
 28+ if( isset( $args['lang'] ) ) {
 29+ $lang = $args['lang'];
 30+ } else {
 31+ return self::formatError( htmlspecialchars( wfMsgForContent( 'syntaxhighlight-err-language' ) ) );
 32+ }
 33+ if( !preg_match( '/^[A-Za-z_0-9-]*$/', $lang ) )
 34+ return self::formatError( htmlspecialchars( wfMsgForContent( 'syntaxhighlight-err-language' ) ) );
 35+ $geshi = self::prepare( $text, $lang );
 36+ if( !$geshi instanceof GeSHi )
 37+ return self::formatError( htmlspecialchars( wfMsgForContent( 'syntaxhighlight-err-language' ) ) );
 38+ // "Enclose" parameter
 39+ $enclose = isset( $args['enclose'] ) && $args['enclose'] == 'div'
 40+ ? GESHI_HEADER_DIV
 41+ : GESHI_HEADER_PRE;
 42+ // Line numbers?
 43+ if( isset( $args['line'] ) ) {
 44+ // Force <div> mode to maintain valid XHTML, see
 45+ // http://sourceforge.net/tracker/index.php?func=detail&aid=1201963&group_id=114997&atid=670231
 46+ $enclose = GESHI_HEADER_DIV;
 47+ $geshi->enable_line_numbers( GESHI_FANCY_LINE_NUMBERS );
 48+ }
 49+ // Starting line number
 50+ if( isset( $args['start'] ) )
 51+ $geshi->start_line_numbers_at( $args['start'] );
 52+ $geshi->set_header_type( $enclose );
 53+ // Strict mode
 54+ if( isset( $args['strict'] ) )
 55+ $geshi->enable_strict_mode();
 56+ // Format
 57+ $out = $geshi->parse_code();
 58+ $err = $geshi->error();
 59+ if( $err ) {
 60+ // Error!
 61+ return self::formatError( $err );
 62+ } else {
 63+ // Armour for Parser::doBlockLevels()
 64+ if( $enclose == GESHI_HEADER_DIV )
 65+ $out = str_replace( "\n", '', $out );
 66+ // Register CSS
 67+ $parser->mOutput->addHeadItem( self::buildHeadItem( $geshi ), "source-{$lang}" );
 68+ return $out;
 69+ }
 70+ }
 71+
 72+ /**
 73+ * Hook into Article::view() to provide syntax highlighting for
 74+ * custom CSS and JavaScript pages
 75+ *
 76+ * @param string $text
 77+ * @param Title $title
 78+ * @param OutputPage $output
 79+ * @return bool
 80+ */
 81+ public static function viewHook( &$text, $title, $output ) {
 82+ // Determine the language
 83+ preg_match( '!\.(css|js)$!u', $title->getText(), $matches );
 84+ $lang = $matches[1] == 'css' ? 'css' : 'javascript';
 85+ // Attempt to format
 86+ $geshi = self::prepare( $text, $lang );
 87+ if( $geshi instanceof GeSHi ) {
 88+ $out = $geshi->parse_code();
 89+ if( !$geshi->error() ) {
 90+ // Done
 91+ $output->addHeadItem( "source-$lang", self::buildHeadItem( $geshi ) );
 92+ $text = $out;
 93+ return false;
 94+ }
 95+ }
 96+ // Bottle out
 97+ return true;
 98+ }
 99+
 100+ /**
 101+ * Initialise a GeSHi object to format some code, performing
 102+ * common setup for all our uses of it
 103+ *
 104+ * @param string $text
 105+ * @param string $lang
 106+ * @return GeSHi
 107+ */
 108+ private static function prepare( $text, $lang ) {
 109+ self::initialise();
 110+ $geshi = new GeSHi( $text, $lang );
 111+ if( $geshi->error() == GESHI_ERROR_NO_SUCH_LANG )
 112+ return null;
 113+ $geshi->set_encoding( 'UTF-8' );
 114+ $geshi->enable_classes();
 115+ $geshi->set_overall_class( "source-$lang" );
 116+ $geshi->enable_keyword_links( false );
 117+ return $geshi;
 118+ }
 119+
 120+ /**
 121+ * Prepare a CSS snippet suitable for use as a ParserOutput/OutputPage
 122+ * head item
 123+ *
 124+ * @param GeSHi $geshi
 125+ * @return string
 126+ */
 127+ private static function buildHeadItem( $geshi ) {
 128+ global $wgUseSiteCss, $wgSquidMaxage;
 129+ $lang = $geshi->language;
 130+ $css[] = '<style type="text/css">/*<![CDATA[*/';
 131+ $css[] = ".source-$lang {line-height: normal;}";
 132+ $css[] = ".source-$lang li {line-height: normal;}";
 133+ $css[] = $geshi->get_stylesheet( false );
 134+ if( $wgUseSiteCss ) {
 135+ $title = Title::makeTitle( NS_MEDIAWIKI, 'Geshi.css' );
 136+ $q = "usemsgcache=yes&action=raw&ctype=text/css&smaxage={$wgSquidMaxage}";
 137+ $css[] = '@import "' . $title->getLocalUrl( $q ) . '";';
 138+ }
 139+ $css[] = '/*]]>*/';
 140+ $css[] = '</style>';
 141+ return implode( "\n", $css );
 142+ }
 143+
 144+ /**
 145+ * Format an error message
 146+ *
 147+ * @param string $error
 148+ * @return string
 149+ */
 150+ private static function formatError( $error = '' ) {
 151+ $html = '';
 152+ if( $error )
 153+ $html .= "<p>{$error}</p>";
 154+ $html .= '<p>' . htmlspecialchars( wfMsgForContent( 'syntaxhighlight-specify' ) )
 155+ . ' <samp>&lt;source lang=&quot;html&quot;&gt;...&lt;/source&gt;</samp></p>'
 156+ . '<p>' . htmlspecialchars( wfMsgForContent( 'syntaxhighlight-supported' ) ) . '</p>'
 157+ . self::formatLanguages();
 158+ return "<div style=\"border: solid red 1px; padding: .5em;\">{$html}</div>";
 159+ }
 160+
 161+ /**
 162+ * Format the list of supported languages
 163+ *
 164+ * @return string
 165+ */
 166+ private static function formatLanguages() {
 167+ $langs = self::getSupportedLanguages();
 168+ $list = array();
 169+ if( count( $langs ) > 0 ) {
 170+ for( $i = 0; $i < count( $langs ); $i++ ) {
 171+ if( preg_match( '!/([^\.]+)\.php$!u', $langs[$i], $m ) )
 172+ $list[] = '<samp>' . $m[1] . '</samp>';
 173+ }
 174+ return '<p style="padding: 0em 1em;">' . implode( ', ', $list ) . '</p>';
 175+ } else {
 176+ return '<p>' . htmlspecialchars( wfMsgForContent( 'syntaxhighlight-err-loading' ) ) . '</p>';
 177+ }
 178+ }
 179+
 180+ /**
 181+ * Get the list of supported languages
 182+ *
 183+ * @return array
 184+ */
 185+ private static function getSupportedLanguages() {
 186+ if( !is_array( self::$languages ) ) {
 187+ self::initialise();
 188+ self::$languages = glob( GESHI_LANG_ROOT . "/*.php" );
 189+ sort( self::$languages );
 190+ }
 191+ return self::$languages;
 192+ }
 193+
 194+ /**
 195+ * Initialise messages and ensure the GeSHi class is loaded
 196+ */
 197+ private static function initialise() {
 198+ global $wgMessageCache;
 199+ if( !self::$initialised ) {
 200+ require_once( dirname( __FILE__ ) . '/SyntaxHighlight_GeSHi.i18n.php' );
 201+ foreach( efSyntaxHighlight_GeSHiMessages() as $lang => $messages )
 202+ $wgMessageCache->addMessages( $messages, $lang );
 203+ if( !class_exists( 'GeSHi' ) )
 204+ require( 'geshi/geshi.php' );
 205+ self::$initialised = true;
 206+ }
 207+ }
 208+
 209+}
\ No newline at end of file
Property changes on: trunk/extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.class.php
___________________________________________________________________
Name: svn:eol-style
1210 + native

Status & tagging log