File Coverage

blib/lib/Pistachio/Html.pm
Criterion Covered Total %
statement 62 62 100.0
branch 7 12 58.3
condition 2 4 50.0
subroutine 14 14 100.0
pod 0 4 0.0
total 85 96 88.5


line stmt bran cond sub pod time code
1             package Pistachio::Html;
2             # ABSTRACT: provides snippet(), which turns source code text into stylish HTML
3              
4 3     3   22814 use strict;
  3         6  
  3         100  
5 3     3   15 use warnings;
  3         6  
  3         117  
6             our $VERSION = '0.10'; # VERSION
7              
8 3     3   578 use Pistachio::Tokenizer;
  3         6  
  3         62  
9 3     3   884 use Pistachio::Language;
  3         5  
  3         175  
10 3     3   2874 use HTML::Entities;
  3         29205  
  3         356  
11 3     3   34 use Module::Load;
  3         4  
  3         24  
12 3     3   168 use Carp 'croak';
  3         6  
  3         2602  
13              
14             # @param string $type Object type.
15             # @param mixed $lang String: language, e.g., 'Perl5'.
16             # Object: A Pistachio::Language.
17             # @param string $style Style, e.g., 'Github'.
18             # @return Pistachio::Html
19             sub new {
20 4     4 0 41 my $type = shift;
21 4   50     29 my ($lang, $style) = (shift || '', shift || '');
      50        
22              
23             # A Pistachio::Css's methods return the Language-independent
24             # CSS definitions that correspond to the given style.
25 4         15 my $Css = "Pistachio::Css::${style}";
26 4         9 eval { load $Css };
  4         100  
27 4 50       114 croak "No CSS support for `$style`" if $@;
28 4         26 my $css = $Css->new;
29              
30             # If $lang is a Pistachio::Language, then there is no
31             # more work to do. If $lang is a string, attempt to
32             # construct a corresponding Pistachio::Language.
33             # (Right now, baked-in language support is limited
34             # to Perl5, which is tokenized via PPI::Tokenizer.)
35 4 50       17 ref $lang eq 'Pistachio::Language' or do {
36 4         6 eval { load "${Css}::${lang}", 'type_to_style' };
  4         22  
37 4 50       347 croak "No type_to_style() for `$lang, $style`" if $@;
38              
39 4         9 eval { load "Pistachio::Token::Constructor::${lang}",
  4         20  
40             'text_to_tokens' };
41 4 50       375 croak "No text_to_tokens() for `$lang`" if $@;
42              
43 4         8 eval { load "Pistachio::Token::Transformer::${lang}",
  4         29  
44             'transform_rules' };
45 4 50       316 croak "No transform_rules() for `$lang`" if $@;
46              
47             $lang = Pistachio::Language->new(
48             $lang,
49 4     4   21 tokens => sub { text_to_tokens($_[0]) },
50 4     4   16 type_to_style => sub { type_to_style($_[0]) },
51 23     23   62 transform_rules => sub { transform_rules() },
52 4         69 );
53             };
54              
55 4         31 bless [$lang, $css], $type;
56             }
57              
58             # @param Pistachio::Html $this
59             # @return A Pistachio::Language
60 6     6 0 48 sub lang { shift->[0] }
61              
62             # @param Pistachio::Html $this
63             # @return Pistachio::Css Provides methods to access language-independent
64             # css definitions, for the given style.
65 3     3 0 28 sub css { shift->[1] }
66              
67             # @param Pistachio::Html $this
68             # @param scalarref $text source code text
69             # @return string line numbers div + source code div html
70             sub snippet {
71 1     1 0 2 my ($this, $text) = @_;
72              
73 1         3 NUMBER_STRIP: my $num_strip = do {
74 1         3 my @nums = 1 .. @{[split /\n/, $$text]};
  1         8  
75 1         4 my $spec = '
%d
';
76 1         7 my @divs = map sprintf($spec, $this->css->number_cell, $_), @nums;
77              
78 1         3 $spec = qq{
\n%s\n
\n};
79 1         3 sprintf $spec, $this->css->number_strip, "@divs";
80             };
81              
82 1         3 CODE_DIV: my $code_div = do {
83 1         2 my $code = '';
84 1         5 my $it = Pistachio::Tokenizer->new($this->lang)->iterator($text);
85              
86 1         5 while ($_ = $it->()) {
87 4         13 my $style = $this->lang->type_to_style($_->type);
88 4         14 my $val = encode_entities $_->value;
89 4 100       91 $code .= $style ? qq|$val|
90             : qq|$val|;
91             }
92              
93 1         6 sprintf qq{
%s
}, $this->css->code_div, $code;
94             };
95              
96 1         10 join "\n", '
', $num_strip, $code_div, '
',
97             '
';
98             }
99              
100             1;
101              
102             __END__