| 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__ |