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) = @_;