File Coverage

blib/lib/Dancer2/Plugin/SyntaxHighlight/Perl.pm
Criterion Covered Total %
statement 37 37 100.0
branch 8 8 100.0
condition n/a
subroutine 10 10 100.0
pod 2 2 100.0
total 57 57 100.0


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::SyntaxHighlight::Perl;
2              
3             our $VERSION = '0.0009';
4              
5 5     5   2632014 use strict; use warnings;
  5     5   40  
  5         155  
  5         32  
  5         13  
  5         153  
6 5     5   461 use Data::Dumper; $Data::Dumper::Indent = $Data::Dumper::Sortkeys = 1;
  5         5321  
  5         363  
7 5     5   2207 use Dancer2::Plugin;
  5         238873  
  5         51  
8 5     5   54164 use PPI::HTML;
  5         458980  
  5         1917  
9              
10             plugin_keywords(qw/
11             highlight_perl
12             highlight_output
13             /);
14              
15             has line_numbers => (
16                 is => 'lazy',
17 3 100   3   117     builder => sub { $_[0]->config->{'line_numbers'} || 0 },
18             );
19              
20             has skip_postprocessing => (
21                 is => 'lazy',
22 4 100   4   157     builder => sub { $_[0]->config->{'skip_postprocessing'} || 0 },
23             );
24              
25             sub highlight_perl {
26 4     4 1 356714     my ( $self, $code ) = @_;
27              
28 4         11     my $perl = $code;
29 4         126     my $PPI = PPI::HTML->new( line_numbers => $self->line_numbers );
30 4         329     my $html = $PPI->html( $perl );
31              
32 4         126367     return $self->_postprocess( $html );
33             }
34              
35             sub highlight_output {
36 2     2 1 1886     my ( $self, $output ) = @_;
37              
38 2         21     my $raw = PPI::Document->new( $output )->content;
39 2         16618     my @lines = split "\n", $raw;
40 2         667     my $line_number = 0;
41 2         5     my $html;
42 2         8     for ( @lines ) {
43 26 100       65         my $class = ++$line_number == 1 ? 'prompt' : 'output';
44 26         58         $html .= qq{<span class="$class">$_</span><br>};
45                 }
46              
47 2         11     return $self->_postprocess( $html );
48             };
49              
50             sub _postprocess {
51 6     6   63     my ( $self, $html ) = @_;
52 6 100       283     return $html if $self->skip_postprocessing;
53              
54 5         272     $html =~ s/<BR>/\n/gi;
55 5         41     $html =~ s/\n{2}/\n/msg;
56 5         842     $html =~ s/(?:\A\s+|\s+\Z)//msg;
57              
58 5         133     return $html;
59             }
60              
61             1;
62              
63             __END__
64            
65             =pod
66            
67             =head1 VERSION
68            
69             version 0.0009
70            
71             =head1 NAME
72            
73             Dancer2::Plugin::SyntaxHighlight::Perl - Generate pretty HTML from Perl code in a Dancer2 app
74            
75             =head1 DESCRIPTION
76            
77             This module provides on-the-fly conversion of Perl to syntax-highlighted HTML. For convenience it adds the keywords C<highlight_perl> and C<highlight_output> to the Dancer2 DSL.
78            
79             =head1 SYNOPSIS
80            
81             =head2 Configuration
82            
83             plugins:
84             'SyntaxHighlight::Perl':
85             line_numbers: 1
86            
87             =head2 Application code
88            
89             get '/perl_tutorial' => sub {
90             return template 'perl_tutorial', {
91             example_code => highlight_perl('/path/to/file.pl'),
92             example_output => highlight_output('/path/to/file.txt'),
93             };
94             };
95            
96             =head2 HTML template
97            
98             <div style="white-space: pre-wrap">
99             [% example_code %]
100             </div>
101            
102             Or:
103            
104             <div>
105             <pre>[%example_code %]</pre>
106             </div>
107            
108             =head1 EXAMPLE OUTPUT
109            
110             =for HTML <p><img src="https://raw.githubusercontent.com/1nickt/Dancer2-Plugin-SyntaxHighlight-Perl/master/examples/background-light-code.png"></p>
111            
112             =head1 FUNCTIONS
113            
114             =head2 highlight_perl
115            
116             Takes as input the full pathname of a file, or a filehandle, or a reference to a scalar. Expects what it is given to contain Perl code.
117            
118             Outputs Perl code as HTML with syntax highlighting, in the form of C<< <span></span> >> tags, with the appropriate class names, around the elements of the Perl code after it has been parsed by C<PPI>.
119            
120             If C<line_numbers> is set to true in the Dancer2 config, the output will have line numbers.
121            
122             For more details on the format of the ouput, see C<PPI::HTML>, or examine the files in the C<examples/> directory in this distribution.
123            
124             You will need to provide the CSS for the styling, see C<examples/> for examples.
125            
126             B<Important>: This module removes the C<< <BR> >> tags from the end of the generated HTML lines, so you B<must> enclose the HTML in either C<< <pre></pre> >> tags or an element with C<style="white-space: pre-wrap">>.
127            
128             You can override this transformation by setting C<skip_postprocessing> to true in the Dancer2 config.
129            
130             =head2 highlight_output
131            
132             Often when showing Perl code you will want to show also the output of the code, This function adds very simple highlighting to the saved output of Perl code.
133            
134             Takes as input the full pathname of a file, or a filehandle, or a reference to a scalar.
135            
136             Outputs the content with the first line wrapped in a C<< <span></span> >> tag with the special class C<prompt>, and all other with the class C<word>.
137            
138             This generated HTML also must be enclosed in either C<< <pre></pre> >> tags or an element with C<style="white-space: pre-wrap"> (or set C<skip_postprocessing> to true in the Dancer2 config).
139            
140             =head1 SEE ALSO
141            
142             C<PPI>, C<PPI::HTML>
143            
144             =head1 AUTHOR
145            
146             Nick Tonkin <tonkin@cpan.org>
147            
148             =head1 COPYRIGHT AND LICENSE
149            
150             This software is copyright (c) 2017 by Nick Tonkin.
151            
152             This is free software; you can redistribute it and/or modify it under
153             the same terms as the Perl 5 programming language system itself.
154            
155             =cut
156