package MojoMojo::Formatter::SyntaxHighlight; use strict; use warnings; use base qw/MojoMojo::Formatter/; use HTML::Entities; eval "use Syntax::Highlight::Engine::Kate;"; my $eval_res = $@; sub module_loaded { $eval_res ? 0 : 1 } my $main_formatter; eval { $main_formatter = MojoMojo->pref('main_formatter'); }; $main_formatter ||= 'MojoMojo::Formatter::Markdown'; =head1 NAME MojoMojo::Formatter::SyntaxHighlight - syntax highlighting for code blocks =head1 DESCRIPTION This formatter performs syntax highlighting on code blocks. =head1 METHODS =over 4 =item format_content_order The syntax highlight formatter is based on EpreE tags and therefore it's elementary to get those unchanged. So we need to run this plugin before L which actually changes those tags. =cut sub format_content_order { 99 } =item format_content This formatter uses L to highlight code syntax inside of
 
tags. To let the formatter know which language has to be highlighted, do:
   say "Hola Mundo";
 
See L for a list of supported languages. =cut # NOTE: Moved $kate outside of format_content method because # of apparent memory links so we want to re-use the object instead # of creating a new one each time a page is requested. my $kate = _kate(); sub format_content { my ( $class, $content ) = @_; return unless $class->module_loaded; my @blocks = (); my $ph = 0; my $ph_base = __PACKAGE__ . '::PlaceHolder::'; # new school - consistent with other new syntax, but broke for me to the point of exhaustion # $$content =~ s/\{\{\s*code\s+lang=""\s*\}\}/
/g;
# while ( $$content =~ s/\{\{\s*code(?:\s+lang=['"]*(.*?)['"]*")?\s*\}\}(.*?)\{\{\s*end\s*\}\}/$ph_base$ph/si ) {
# old school - which works with textile2 (not textile for mxh)
# drop all lang=""
    $$content =~ s/<\s*pre\s+lang=""\s*>/
/g;
    while ( $$content =~ s/<\s*pre(?:\s+lang=['"]*(.*?)['"]*")?\s*>(.*?)<\s*\/pre\s*>/$ph_base$ph/si ) {
        my ( $language, $block ) = ( $1, $2 );

        # Fix newline issue
        $block =~ s/\r//g;

# Unfortunately markdown also encodes entities at some level which is not possible to disable
# neither easy to hack like we do for textile. So let's decode & to & to avoid:
# > => &gt;
        $block =~ s/&/&/g;

        $block = decode_entities($block);
        if ($language) {
            eval {
                $kate->language($language);
                if ( $language eq 'HTML' ) {

                    # We want HTML entities for HTML Hightlight
                    # Yeah, this is sub-optimal.
                    $kate->substitutions->{"<"} = "<";
                    $kate->substitutions->{">"} = ">";
                    $kate->substitutions->{"&"} = "&";
                }
            };
            unless ($@) {
                $block = $kate->highlightText($block);
            }
        }
        push @blocks, $block;
        $ph++;
    }

    for ( my $i = 0 ; $i < $ph ; $i++ ) {
        $$content =~ s/$ph_base$i/
$blocks[$i]<\/pre>/;
    }

    return $content;
}

sub _kate {
    return Syntax::Highlight::Engine::Kate->new(
        language      => 'Perl',
        substitutions => {
            " "  => " ",
            "\t" => "   ",
            "\n" => "\n",
        },
        format_table => {
            Alert    => [ q{},      "" ],
            BaseN    => [ q{},      "" ],
            BString  => [ q{},    "" ],
            Char     => [ q{},       "" ],
            Comment  => [ q{}, "" ],
            DataType => [ q{},   "" ],
            DecVal   => [ q{},     "" ],
            Error => [ q{}, "" ],
            Float => [ q{},       "" ],
            Function => [ q{}, "" ],
            IString  => [ q{},  "" ],
            Keyword  => [ q{},                         "" ],
            Normal   => [ q{},                            "" ],
            Operator => [ q{}, "" ],
            Others   => [ q{},   "" ],
            RegionMarker =>
              [ q{}, "" ],
            Reserved => [ q{}, "" ],
            String   => [ q{},      "" ],
            Variable => [ q{}, "" ],
            Warning =>
              [ q{}, "" ],
        },
    );
}

=back

=head1 SEE ALSO

L, L and L.

=head1 AUTHORS

Johannes Plunien Eplu@cpan.orgE

=head1 LICENSE

This module is licensed under the same terms as Perl itself.

=cut

1;