diff options
Diffstat (limited to 'lib/IkiWiki/Plugin')
-rw-r--r-- | lib/IkiWiki/Plugin/highlight.pm | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/lib/IkiWiki/Plugin/highlight.pm b/lib/IkiWiki/Plugin/highlight.pm index f2de12d..860b9c3 100644 --- a/lib/IkiWiki/Plugin/highlight.pm +++ b/lib/IkiWiki/Plugin/highlight.pm @@ -7,7 +7,12 @@ use Syntax::Highlight::Engine::Kate; # variables {{{ my %hl_args = ( - substitutions => { }, + substitutions => { + '<' => '<', + '>' => '>', + '&' => '&', + '[' => '[', # wow is this a huge hack + }, format_table => { Alert => ["<span class='synAlert'>", "</span>"], BaseN => ["<span class='synBaseN'>", "</span>"], @@ -31,35 +36,47 @@ my %hl_args = ( Warning => ["<span class='synWarning'>", "</span>"], }, ); -my %syntaxes; +my $syntaxes; # }}} sub import { # {{{ - hook(type => 'sanitize', id => __PACKAGE__, call => \&sanitize, first => 1); + my $hl = Syntax::Highlight::Engine::Kate->new(%hl_args); + $syntaxes = { map { +lc($_) => $hl->syntaxes->{$_} } + keys %{ $hl->syntaxes } }; + $syntaxes->{c} = 'ANSI C89'; + $syntaxes->{cpp} = 'C++'; + $syntaxes->{ocaml} = 'Objective Caml'; + hook(type => 'filter', id => __PACKAGE__, call => \&filter); } # }}} -sub sanitize { # {{{ +sub filter { # {{{ my %args = @_; my $content = ''; + my $code_block = ''; my $in_code = 0; + my $code_re = qr/^(?: {4}|\t)/; + my $empty_re = qr/^\s*$/; for my $line (split /^/m, $args{content}) { if ($in_code) { - if ($line =~ s{(</code></pre>.*)}{}s) { - my $rest_line = $1; + if ($line =~ $code_re || $line =~ $empty_re) { + $line =~ s/^(?: ? ? ? ?|\t)//; $code_block .= $line; - $content .= highlight($code_block) . $rest_line; - $code_block = ''; - $in_code = 0; } else { - $code_block .= $line; + $code_block =~ s/(\s*)$//; + my $ws = $1; + $content .= highlight($code_block); + $in_code = 0; + $code_block = ''; + $content .= $ws; + $content .= $line; } } else { - if ($line =~ s{(.*<pre><code>)}{}s) { - $content .= $1; - $code_block .= $line; + if ($line =~ $code_re && $line !~ $empty_re) { $in_code = 1; + $line =~ s/^(?: ? ? ? ?|\t)//; + $code_block .= $line; } else { $content .= $line; @@ -73,21 +90,31 @@ sub sanitize { # {{{ sub highlight { # {{{ my ($code_block) = @_; my $filetype = guess_filetype($code_block); - return unless $filetype; - my $hl = Syntax::Highlight::Engine::Kate->new( - language => $filetype, %hl_args - ); - %syntaxes ||= map { lc($_) => $hl->syntaxes->{$_} } keys %$hl->syntaxes; - return $hl->highlightText($code_block); + return $code_block unless $filetype; + my $hl = Syntax::Highlight::Engine::Kate->new(%hl_args, + language => $filetype); + $code_block =~ s/[^\n]*\n//s; + $filetype =~ s/\s/_/g; + return "<pre><code class='lang$filetype'>" . + $hl->highlightText($code_block) . + '</code></pre>'; } # }}} sub guess_filetype { # {{{ my ($code_block) = @_; my ($first_line) = split /\n/, $code_block; - if ($first_line =~ /^#!(\w+)/) { - return $syntaxes{$1}; + if ($first_line =~ m{^#!\s*(?:.+[\s/]+)*(\w+)}) { + return $syntaxes->{$1}; + } + elsif ($first_line =~ m{^[/(]\*\s*(\w+)\s*\*[/)]}) { + return $syntaxes->{$1}; + } + elsif ($first_line =~ m{^[-/]{2}\s*(\w+)}) { + return $syntaxes->{$1}; + } + elsif ($first_line =~ m{^<!--\s*(\w+)\s*-->}) { + return $syntaxes->{$1}; } - return; } # }}} 1; |