For a more lightweight implementation, see /SourceHighlight2
This patch uses the GNU source-highlight package (available from http://www.gnu.org/software/src-highlite/). With this patch you can enclose source code snippets between special tags, and have them show up properly highlighted on the page. The html output has the class codefragment. I would add something like this to wiki.css to make the output look neat:
PRE.codefragment { border: 1px solid #CCCCCC; background-color: #f5f5f5; margin: 4px 8px 4xp 2px; padding: 4px 6px; }
The tags are <code language> and </code>. The language can be anything that your version of source-highlight supports, e.g. cpp, perl, java, etc.
The $SourceHighlight? config variable must be set to wherever the source-highlight binary is installed. The default is /usr/local/bin/source-highlight.
TODO: The current implementation requests a global lock for the duration of source-highlight. This should be replaced with a smarter locking mechanism.
NOTE: This patch starts a source-highlight process for each piece of hightlighted code in a wiki page. If your server is heavily loaded, use /SourceHighlight2 instead.
--- wiki.pl 2003-09-11 14:21:02.000000000 +0200 +++ SourceHighlight.pl 2005-10-21 11:38:22.000000000 +0200 @@ -53,7 +53,9 @@ @IsbnNames @IsbnPre @IsbnPost $EmailFile $FavIcon $RssDays $UserHeader $UserBody $StartUID $ParseParas $AuthorFooter $UseUpload $AllUpload $UploadDir $UploadUrl $LimitFileUrl $MaintTrimRc $SearchButton - $EditNameLink $UseMetaWiki @ImageSites $BracketImg ); + $EditNameLink $UseMetaWiki @ImageSites $BracketImg + $SourceHighlight + ); # Note: $NotifyDefault is kept because it was a config variable in 0.90 # Other global variables: use vars qw(%Page %Section %Text %InterSite %SaveUrl %SaveNumUrl @@ -89,6 +91,7 @@ $NotFoundPg = ""; # Page for not-found links ("" for blank pg) $EmailFrom = "Wiki"; # Text for "From: " field of email notes. $SendMail = "/usr/sbin/sendmail"; # Full path to sendmail executable +$SourceHighlight = "/usr/local/bin/source-highlight"; # GNU sourcehighlight for <CODE> $FooterNote = ""; # HTML for bottom of every page $EditNote = ""; # HTML notice above buttons on edit page $MaxPost = 1024 * 210; # Maximum 210K posts (about 200K for pages) @@ -1580,6 +1583,8 @@ $pageText =~ s/\<pre\>((.|\n)*?)\<\/pre\>/&StorePre($1, "pre")/ige; $pageText =~ + s/\<code(?:\s+(\w+))?\>((.|\n)*?)\<\/code\>/&StoreCode($2, $1)/ige; + $pageText =~ s/\<code\>((.|\n)*?)\<\/code\>/&StorePre($1, "code")/ige; $pageText =~ s/((.|\n)+?\n)\s*\n/&ParseParagraph($1)/geo; $pageText =~ s/(.*)<\/p>(.+)$/$1.&ParseParagraph($2)/seo; @@ -1607,6 +1612,7 @@ s/\<nowiki\>((.|\n)*?)\<\/nowiki\>/&StoreRaw($1)/ige; # The <pre> tag wraps the stored text with the HTML <pre> tag s/\<pre\>((.|\n)*?)\<\/pre\>/&StorePre($1, "pre")/ige; + s/\<code(?:\s+(\w+))?\>((.|\n)*?)\<\/code\>/&StoreCode($2, $1)/ige; s/\<code\>((.|\n)*?)\<\/code\>/&StorePre($1, "code")/ige; if ($EarlyRules ne '') { $_ = &EvalLocalRules($EarlyRules, $_, !$useImage); @@ -1894,6 +1900,62 @@ return &StoreRaw("<$tag>" . $html . "</$tag>"); } +sub StoreCode { + my ($text, $lang) = @_; + + if ($SourceHighlight eq '' || not defined $lang) { + return &StorePre($text, 'CODE'); + } + + &RequestLock(); + + $text =~ s/</</g; + $text =~ s/>/>/g; + $text =~ s/&/&/g; + my $this_cmd = "$SourceHighlight -f html -t 4 -s $lang"; + my $tmp_file = "$TempDir/highlight"; + + eval { open( TMP, "> $tmp_file" ) || die $! }; + if ( $@ ) { + &ReleaseLock(); + return &StoreRaw("Failed to open temp file [$tmp_file] for writing: $@" ); + } + print TMP $text; + close( TMP ); + + eval { open( CMD, "$this_cmd < $tmp_file |" ) || die $! }; + if ( $@ ) { + &ReleaseLock(); + return &StoreRaw("Failed to open pipe to command [$this_cmd]: $@" ); + } + my @lines = <CMD>; + close( CMD ); + + unless (unlink( $tmp_file )) { + &ReleaseLock(); + return &StoreRaw( "Error: cannot delete temp file [$tmp_file]: $@" ); + } + + &ReleaseLock(); + + # Cosmetic: Get rid of lines 1 and 2 (0-based), plus the + # next-to-last line + + while ($lines[0] =~ /^(<tt>|<pre>|\s+)*$/i) { + splice( @lines, 0, 1 ); + } + while ($lines[scalar @lines - 1] =~ /^(<\/tt>|<\/pre>|\s+)*$/i) { + splice( @lines, scalar @lines - 1, 1 ); + } + # splice( @lines, 1, 2 ); + # splice( @lines, scalar @lines - 2, 1 ); + + return &StoreRaw(join( '', + qq(<pre class="codefragment">), + @lines, + qq(</pre>))); +} + sub StoreHref { my ($anchor, $text) = @_;