File Coverage

blib/lib/MojoMojo/Formatter/SyntaxHighlight.pm
Criterion Covered Total %
statement 32 32 100.0
branch 4 6 66.6
condition n/a
subroutine 7 7 100.0
pod 3 3 100.0
total 46 48 95.8


line stmt bran cond sub pod time code
1             package MojoMojo::Formatter::SyntaxHighlight;
2              
3 26     26   14945 use strict;
  26         75  
  26         667  
4 26     26   125 use warnings;
  26         60  
  26         720  
5 26     26   479 use parent qw/MojoMojo::Formatter/;
  26         260  
  26         130  
6 26     26   1690 use HTML::Entities;
  26         4599  
  26         11132  
7              
8             eval {require Syntax::Highlight::Engine::Kate};
9             my $kate_installed = !$@;
10              
11             =head2 module_loaded
12              
13             Return true if the module is loaded.
14              
15             =cut
16              
17 171     171 1 253874 sub module_loaded { $kate_installed }
18              
19             my $main_formatter;
20             eval { $main_formatter = MojoMojo->pref('main_formatter'); };
21             $main_formatter ||= 'MojoMojo::Formatter::Markdown';
22              
23             =head1 NAME
24              
25             MojoMojo::Formatter::SyntaxHighlight - syntax highlighting for code blocks
26              
27             =head1 DESCRIPTION
28              
29             This formatter performs syntax highlighting on code blocks.
30              
31             =head1 METHODS
32              
33             =head2 format_content_order
34              
35             The syntax highlight formatter is based on C<< <pre> >> tags entered by the
36             user, so it must run before other formatters that produce C<< <pre> >> tags.
37             The earliest such formatter is the main formatter.
38              
39             =cut
40              
41 992     992 1 3461 sub format_content_order { 14 }
42              
43             =head2 format_content
44              
45             This formatter uses L<Syntax::Highlight::Engine::Kate> to syntax highlight code
46             inside of C<< <pre lang="language"> ... </pre> >> tags:
47              
48             <pre lang="Perl">
49             say "Hello world!";
50             </pre>
51              
52             See L<Syntax::Highlight::Engine::Kate/PLUGINS> for a list of supported
53             languages.
54              
55             =cut
56              
57             # The $kate formatter is scoped outside of format_content. Otherwise, memory
58             # leaks have occurred. This is also faster, as it avoids instantiation for every
59             # request.
60             my $kate;
61              
62             sub format_content {
63 130     130 1 25173 my ( $class, $content ) = @_;
64 130 50       537 return unless $class->module_loaded;
65              
66 130         377 my @blocks = ();
67 130         683 my $ph = 0;
68 130         322 my $ph_base = __PACKAGE__ . '::PlaceHolder::';
69              
70             # new school - consistent with other new syntax, but broke for me to the point of exhaustion
71             # $$content =~ s/\{\{\s*code\s+lang=""\s*\}\}/<pre>/g;
72             # while ( $$content =~ s/\{\{\s*code(?:\s+lang=['"]*(.*?)['"]*")?\s*\}\}(.*?)\{\{\s*end\s*\}\}/$ph_base$ph/si ) {
73             # drop all lang="" -- mateu
74 130         619 $$content =~ s/<\s*pre\s+lang=""\s*>/<pre>/g;
75 130         1220 while ( $$content =~ s/<\s*pre(?:\s+lang=['"]*(.*?)['"]*")?\s*>(.*?)<\s*\/pre\s*>/$ph_base$ph/si ) {
76 37         181 my ( $language, $block ) = ( $1, $2 );
77              
78             # Fix newline issue
79 37         155 $block =~ s/\r//g;
80              
81 37 100       142 if ($language) {
82             eval {
83 32         199 $kate->language($language);
84 32 50       76 } and do {
85 32         30067 $block = $kate->highlightText($block);
86             }
87             }
88 37         854609 push @blocks, $block;
89 37         335 $ph++;
90             }
91              
92 130         587 for ( my $i = 0 ; $i < $ph ; $i++ ) {
93 37         490 $$content =~ s/$ph_base$i/<pre>$blocks[$i]<\/pre>/;
94             }
95              
96 130         446 return $content;
97             }
98              
99             if (module_loaded) {
100             $kate = Syntax::Highlight::Engine::Kate->new(
101             language => 'Perl',
102             substitutions => {
103             "<" => "&lt;",
104             ">" => "&gt;",
105             "&" => "&amp;",
106             "^" => "&circ;",
107             " " => "&nbsp;",
108             "\t" => "&nbsp;&nbsp;&nbsp;&nbsp;",
109             "\n" => "\n",
110             },
111             format_table => {
112             Alert => [ q{<span class="kateAlert">}, "</span>" ],
113             BaseN => [ q{<span class="kateBaseN">}, "</span>" ],
114             BString => [ q{<span class="kateBString">}, "</span>" ],
115             Char => [ q{<span class="kateChar">}, "</span>" ],
116             Comment => [ q{<span class="kateComment"><i>}, "</i></span>" ],
117             DataType => [ q{<span class="kateDataType">}, "</span>" ],
118             DecVal => [ q{<span class="kateDecVal">}, "</span>" ],
119             Error => [ q{<span class="kateError"><b><i>}, "</i></b></span>" ],
120             Float => [ q{<span class="kateFloat">}, "</span>" ],
121             Function => [ q{<span class="kateFunction">}, "</span>" ],
122             IString => [ q{<span class="kateIString">}, "" ],
123             Keyword => [ q{<b>}, "</b>" ],
124             Normal => [ q{}, "" ],
125             Operator => [ q{<span class="kateOperator">}, "</span>" ],
126             Others => [ q{<span class="kateOthers">}, "</span>" ],
127             RegionMarker => [ q{<span class="kateRegionMarker"><i>}, "</i></span>" ],
128             Reserved => [ q{<span class="kateReserved"><b>}, "</b></span>" ],
129             String => [ q{<span class="kateString">}, "</span>" ],
130             Variable => [ q{<span class="kateVariable"><b>}, "</b></span>" ],
131             Warning => [ q{<span class="kateWarning"><b><i>}, "</b></i></span>" ],
132             },
133             );
134             }
135              
136             =head1 SEE ALSO
137              
138             L<MojoMojo>, L<Module::Pluggable::Ordered> and L<Syntax::Highlight::Engine::Kate>.
139              
140             =head1 AUTHORS
141              
142             Johannes Plunien E<lt>plu@cpan.orgE<gt>
143              
144             =head1 LICENSE
145              
146             This library is free software. You can redistribute it and/or modify
147             it under the same terms as Perl itself.
148              
149             =cut
150              
151             1;