| blib/lib/WWW/Slides/SlideShow.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 109 | 154 | 70.7 |
| branch | 28 | 50 | 56.0 |
| condition | 3 | 3 | 100.0 |
| subroutine | 20 | 25 | 80.0 |
| pod | 0 | 13 | 0.0 |
| total | 160 | 245 | 65.3 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package WWW::Slides::SlideShow; | ||||||
| 2 | { | ||||||
| 3 | 6 | 6 | 39433 | use version; our $VERSION = qv('0.0.7'); | |||
| 6 | 13684 | ||||||
| 6 | 37 | ||||||
| 4 | |||||||
| 5 | 6 | 6 | 584 | use warnings; | |||
| 6 | 12 | ||||||
| 6 | 196 | ||||||
| 6 | 6 | 6 | 36 | use strict; | |||
| 6 | 11 | ||||||
| 6 | 175 | ||||||
| 7 | 6 | 6 | 662 | use Carp; | |||
| 6 | 10 | ||||||
| 6 | 562 | ||||||
| 8 | 6 | 6 | 4554 | use English qw( -no_match_vars ); | |||
| 6 | 15443 | ||||||
| 6 | 44 | ||||||
| 9 | |||||||
| 10 | 6 | 6 | 11352 | use Object::InsideOut; | |||
| 6 | 349795 | ||||||
| 6 | 45 | ||||||
| 11 | |||||||
| 12 | # Other recommended modules (uncomment to use): | ||||||
| 13 | # use IO::Prompt; | ||||||
| 14 | # use Perl6::Export; | ||||||
| 15 | # use Perl6::Slurp; | ||||||
| 16 | # use Perl6::Say; | ||||||
| 17 | # use Regexp::Autoflags; | ||||||
| 18 | # use Readonly; | ||||||
| 19 | |||||||
| 20 | # Module implementation here | ||||||
| 21 | my @filename : Field # File to read for slides | ||||||
| 22 | : Get(Name => 'filename') # Public getter | ||||||
| 23 | : Std(Name => 'filename', Private => 1); | ||||||
| 24 | |||||||
| 25 | my @preamble : Field # HTML/whatever preamble | ||||||
| 26 | : Std(Name => 'preamble'); | ||||||
| 27 | my @slides : Field # slide repository | ||||||
| 28 | : Std(Name => 'slides', Private => 1); | ||||||
| 29 | my @postamble : Field # HTML/whatever postamble | ||||||
| 30 | : Std(Name => 'postamble'); | ||||||
| 31 | |||||||
| 32 | sub read_line_by_line : Private { | ||||||
| 33 | 5 | 203 | my $self = shift; | ||||
| 34 | 5 | 9 | my ($iterator) = @_; | ||||
| 35 | |||||||
| 36 | 5 | 9 | my $preamble; | ||||
| 37 | 5 | 17 | while (defined $iterator->()) { | ||||
| 38 | 97 | 136 | $preamble .= $_; | ||||
| 39 | 97 | 100 | 259 | last if / | |||
| 40 | } | ||||||
| 41 | 5 | 162 | $self->set_preamble($preamble); | ||||
| 42 | |||||||
| 43 | 5 | 280 | my @slides; | ||||
| 44 | 5 | 14 | my $slide = ''; | ||||
| 45 | 5 | 8 | my $div_id = ''; | ||||
| 46 | 5 | 10 | my $div_depth = 0; | ||||
| 47 | 5 | 8 | my $div_mark = 0; | ||||
| 48 | 5 | 10 | my $postamble = ''; | ||||
| 49 | 5 | 15 | while (defined $iterator->()) { | ||||
| 50 | 12 | 50 | 36 | if (m{}mxsi) { | |||
| 51 | 0 | 0 | $postamble = $_; | ||||
| 52 | 0 | 0 | last; | ||||
| 53 | } | ||||||
| 54 | 12 | 19 | $slide .= $_; | ||||
| 55 | 12 | 100 | 60 | if (m{ ]*\sid="([^"]*)"}mxsi) { |
|||
| 50 | |||||||
| 56 | 6 | 16 | $div_id = $1; | ||||
| 57 | 6 | 12 | $div_mark = $div_depth++; | ||||
| 58 | } | ||||||
| 59 | elsif (m{ | ||||||
| 60 | 0 | 0 | ++$div_depth; | ||||
| 61 | } | ||||||
| 62 | 12 | 100 | 39 | if (m{}mxsi) { | |||
| 63 | 6 | 50 | 18 | if (--$div_depth == $div_mark) { | |||
| 64 | 6 | 22 | push @slides, {div_id => $div_id, slide => $slide}; | ||||
| 65 | 6 | 10 | $slide = ''; | ||||
| 66 | 6 | 15 | $div_id = ''; | ||||
| 67 | } | ||||||
| 68 | } ## end if (m{}mxsi) | ||||||
| 69 | } ## end while (defined $iterator->... | ||||||
| 70 | 5 | 163 | $self->set_slides(\@slides); | ||||
| 71 | |||||||
| 72 | 5 | 337 | $self->set_postamble($postamble . join('', $iterator->())); | ||||
| 73 | |||||||
| 74 | 5 | 48 | return; | ||||
| 75 | 6 | 6 | 2857 | } ## end sub read_line_by_line : | |||
| 6 | 13 | ||||||
| 6 | 36 | ||||||
| 76 | |||||||
| 77 | sub read_fh : Private { | ||||||
| 78 | 5 | 245 | my $self = shift; | ||||
| 79 | 5 | 11 | my ($fh) = @_; | ||||
| 80 | |||||||
| 81 | return $self->read_line_by_line( | ||||||
| 82 | sub { | ||||||
| 83 | 122 | 100 | 457 | return <$fh> if wantarray; | |||
| 84 | 117 | 443 | return $_ = <$fh>; | ||||
| 85 | } | ||||||
| 86 | 5 | 44 | ); | ||||
| 87 | 6 | 6 | 1844 | } ## end sub read_fh : | |||
| 6 | 15 | ||||||
| 6 | 30 | ||||||
| 88 | |||||||
| 89 | sub read { | ||||||
| 90 | 5 | 5 | 0 | 58840 | my $self = shift; | ||
| 91 | 5 | 17 | my ($what) = @_; | ||||
| 92 | |||||||
| 93 | 5 | 50 | 29 | croak "undefined file to read slide show" unless defined $what; | |||
| 94 | |||||||
| 95 | 5 | 11 | my ($fh, $was_mine); | ||||
| 96 | 5 | 100 | 30 | if (ref $what eq 'SCALAR') { # Straight string, in-memory handle | |||
| 100 | |||||||
| 50 | |||||||
| 97 | 3 | 97 | $self->set_filename(' |
||||
| 98 | 3 | 50 | 3 | 226 | eval { open $fh, '<', $what or die }; # The perl 5.8 way... | ||
| 3 | 118 | ||||||
| 3 | 29 | ||||||
| 3 | 7 | ||||||
| 3 | 26 | ||||||
| 99 | |||||||
| 100 | 3 | 50 | 4982 | if ($EVAL_ERROR) { # Try to use IO::String, if available... | |||
| 101 | 0 | 0 | eval { | ||||
| 102 | 0 | 0 | require IO::String; | ||||
| 103 | 0 | 0 | $fh = IO::String->new($$what); | ||||
| 104 | }; | ||||||
| 105 | } ## end if ($EVAL_ERROR) | ||||||
| 106 | |||||||
| 107 | # I really wouldn't fall back to this, because I've to | ||||||
| 108 | # split it all in advance, but this is the best I can think | ||||||
| 109 | # at the moment | ||||||
| 110 | 3 | 50 | 15 | if ($EVAL_ERROR) { | |||
| 111 | |||||||
| 112 | # split and re-insert newlines. I don't really mind that | ||||||
| 113 | # I could potentially add a newline to the final line. | ||||||
| 114 | 0 | 0 | my @lines = map { "$_\n" } split /\n/, $$what; | ||||
| 0 | 0 | ||||||
| 115 | return $self->read_line_by_line( | ||||||
| 116 | sub { | ||||||
| 117 | 0 | 0 | 0 | 0 | return splice @lines if wantarray; | ||
| 118 | 0 | 0 | return $_ = shift @lines; | ||||
| 119 | } | ||||||
| 120 | 0 | 0 | ); | ||||
| 121 | } ## end if ($EVAL_ERROR) | ||||||
| 122 | |||||||
| 123 | 3 | 9 | $was_mine = 1; | ||||
| 124 | } ## end if (ref $what eq 'SCALAR') | ||||||
| 125 | elsif (ref $what eq 'GLOB') { | ||||||
| 126 | 1 | 33 | $self->set_filename(' |
||||
| 127 | 1 | 77 | $fh = $what; | ||||
| 128 | } | ||||||
| 129 | elsif (ref $what eq 'ARRAY') { # One file per slide | ||||||
| 130 | 0 | 0 | $self->set_filename(' |
||||
| 131 | 0 | 0 | return $self->read_slides(@$what); | ||||
| 132 | } | ||||||
| 133 | else { | ||||||
| 134 | 1 | 37 | $self->set_filename($what); | ||||
| 135 | 1 | 50 | 125 | open $fh, '<', $what | |||
| 136 | or croak "can't open('$what'): $OS_ERROR"; | ||||||
| 137 | 1 | 3 | $was_mine = 1; | ||||
| 138 | } ## end else [ if (ref $what eq 'SCALAR') | ||||||
| 139 | |||||||
| 140 | 5 | 31 | my $retval = $self->read_fh($fh); | ||||
| 141 | 5 | 100 | 44 | close $fh if $was_mine; | |||
| 142 | |||||||
| 143 | 5 | 33 | return $retval; | ||||
| 144 | } ## end sub read | ||||||
| 145 | |||||||
| 146 | sub read_slides { | ||||||
| 147 | 0 | 0 | 0 | 0 | my $self = shift; | ||
| 148 | |||||||
| 149 | 0 | 0 | $self->set_preamble(' | ||||
| 150 | |||||||
| 151 | "http://www.w3.org/TR/html4/loose.dtd"> | ||||||
| 152 | |||||||
| 153 | |||||||
| 154 | |
||||||
| 155 | |||||||
| 156 | |||||||
| 157 | '); | ||||||
| 158 | |||||||
| 159 | 0 | 0 | $self->set_postamble("\n\n"); | ||||
| 160 | |||||||
| 161 | 0 | 0 | my @slides; | ||||
| 162 | 0 | 0 | for my $filename (@_) { | ||||
| 163 | 0 | 0 | my $text = $self->read_slide($filename); | ||||
| 164 | 0 | 0 | my $div_id = 'slide' . scalar @slides; | ||||
| 165 | 0 | 0 | push @slides, | ||||
| 166 | { | ||||||
| 167 | div_id => $div_id, | ||||||
| 168 | slide => qq{\n \n" |
||||||
| 169 | }; | ||||||
| 170 | } ## end for my $filename (@_) | ||||||
| 171 | 0 | 0 | $self->set_slides(\@slides); | ||||
| 172 | 0 | 0 | return 1; | ||||
| 173 | } ## end sub read_slides | ||||||
| 174 | |||||||
| 175 | sub read_slide { # append a slide | ||||||
| 176 | 0 | 0 | 0 | 0 | my $self = shift; | ||
| 177 | 0 | 0 | my ($filename) = @_; | ||||
| 178 | 0 | 0 | require HTML::Parser; | ||||
| 179 | 0 | 0 | 0 | my $parser = HTML::Parser->new(api_version => 3) or die $!; | |||
| 180 | |||||||
| 181 | 0 | 0 | my $text = ''; | ||||
| 182 | my $start_handler = sub { | ||||||
| 183 | 0 | 0 | 0 | my ($tag, $self) = @_; | |||
| 184 | 0 | 0 | 0 | return unless lc($tag) eq 'body'; | |||
| 185 | 0 | 0 | $self->handler(default => sub { $text .= shift }, 'text'); | ||||
| 0 | 0 | ||||||
| 186 | 0 | 0 | $self->handler(start => sub { $text .= shift }, 'text'); | ||||
| 0 | 0 | ||||||
| 187 | $self->handler( | ||||||
| 188 | end => sub { | ||||||
| 189 | 0 | 0 | my ($tagname, $self, $newtext) = @_; | ||||
| 190 | 0 | 0 | 0 | if (lc($tagname) eq 'body') { | |||
| 191 | 0 | 0 | $self->eof(); | ||||
| 192 | } | ||||||
| 193 | else { | ||||||
| 194 | 0 | 0 | 0 | $text .= $newtext if defined $newtext; | |||
| 195 | } | ||||||
| 196 | }, | ||||||
| 197 | 0 | 0 | 'tagname,self,text' | ||||
| 198 | ); | ||||||
| 199 | 0 | 0 | }; | ||||
| 200 | 0 | 0 | $parser->handler(start => $start_handler, 'tagname,self'); | ||||
| 201 | |||||||
| 202 | 0 | 0 | 0 | $parser->parse_file($filename) | |||
| 203 | or die "could not parse '$filename': $OS_ERROR"; | ||||||
| 204 | 0 | 0 | return $text; | ||||
| 205 | } ## end sub read_slide | ||||||
| 206 | |||||||
| 207 | sub add_headers { # Headers are ok for the moment | ||||||
| 208 | 0 | 0 | 0 | 0 | my $self = shift; | ||
| 209 | 0 | 0 | return; | ||||
| 210 | } | ||||||
| 211 | |||||||
| 212 | sub get_ping { | ||||||
| 213 | 1 | 1 | 0 | 1225 | return "\n"; | ||
| 214 | } | ||||||
| 215 | |||||||
| 216 | sub get_show_div { | ||||||
| 217 | 3 | 3 | 0 | 1990 | my $self = shift; | ||
| 218 | 3 | 6 | my ($slide_no) = @_; | ||||
| 219 | 3 | 8 | my $div_id = $self->_get_slide($slide_no)->{div_id}; | ||||
| 220 | 3 | 219 | return "\n"; | ||||
| 221 | } ## end sub get_show_div | ||||||
| 222 | |||||||
| 223 | sub get_hide_div { | ||||||
| 224 | 3 | 3 | 0 | 5 | my $self = shift; | ||
| 225 | 3 | 7 | my ($slide_no) = @_; | ||||
| 226 | 3 | 7 | my $div_id = $self->_get_slide($slide_no)->{div_id}; | ||||
| 227 | 3 | 204 | return "\n"; | ||||
| 228 | } ## end sub get_hide_div | ||||||
| 229 | |||||||
| 230 | sub get_slide { | ||||||
| 231 | 3 | 3 | 0 | 645 | my $self = shift; | ||
| 232 | 3 | 5 | my ($slide_no) = @_; | ||||
| 233 | 3 | 9 | return $self->_get_slide($slide_no)->{slide}; | ||||
| 234 | } | ||||||
| 235 | |||||||
| 236 | sub _get_slide { | ||||||
| 237 | 9 | 9 | 13 | my $self = shift; | |||
| 238 | 9 | 13 | my ($n) = @_; | ||||
| 239 | 9 | 255 | return $self->get_slides()->[$n - 1]; | ||||
| 240 | } | ||||||
| 241 | |||||||
| 242 | sub id_first { | ||||||
| 243 | 4 | 4 | 0 | 1425 | return 1; | ||
| 244 | } | ||||||
| 245 | |||||||
| 246 | sub id_last { | ||||||
| 247 | 2 | 2 | 0 | 592 | my $self = shift; | ||
| 248 | 2 | 5 | return scalar @{$self->get_slides()}; | ||||
| 2 | 54 | ||||||
| 249 | } | ||||||
| 250 | |||||||
| 251 | sub id_next { | ||||||
| 252 | 6 | 6 | 0 | 2275 | my $self = shift; | ||
| 253 | 6 | 9 | my ($id) = @_; | ||||
| 254 | 6 | 100 | 21 | return ($id + 1) if $self->validate_slide_id($id + 1); | |||
| 255 | 2 | 105 | return $id; | ||||
| 256 | } ## end sub id_next | ||||||
| 257 | |||||||
| 258 | sub id_previous { | ||||||
| 259 | 3 | 3 | 0 | 1679 | my $self = shift; | ||
| 260 | 3 | 6 | my ($id) = @_; | ||||
| 261 | 3 | 100 | 8 | return ($id - 1) if $self->validate_slide_id($id - 1); | |||
| 262 | 1 | 3 | return $id; | ||||
| 263 | } ## end sub id_previous | ||||||
| 264 | |||||||
| 265 | sub validate_slide_id { | ||||||
| 266 | 9 | 9 | 0 | 12 | my $self = shift; | ||
| 267 | 9 | 11 | my ($id) = @_; | ||||
| 268 | 9 | 50 | 51 | return if $id !~ /\A\d+\z/; | |||
| 269 | 9 | 100 | 35 | return ($id > 0) && ($id <= @{$self->get_slides()}); | |||
| 270 | } ## end sub validate_slide_id | ||||||
| 271 | |||||||
| 272 | } | ||||||
| 273 | |||||||
| 274 | 1; # Magic true value required at end of module | ||||||
| 275 | __END__ |