File Coverage

lib/Text/Xatena/Node/List.pm
Criterion Covered Total %
statement 59 59 100.0
branch 12 12 100.0
condition 6 6 100.0
subroutine 8 8 100.0
pod 0 3 0.0
total 85 88 96.5


line stmt bran cond sub pod time code
1             package Text::Xatena::Node::List;
2              
3 17     17   87 use strict;
  17         33  
  17         517  
4 17     17   81 use warnings;
  17         31  
  17         435  
5 17     17   85 use base qw(Text::Xatena::Node);
  17         33  
  17         307  
6             use constant {
7 17         24531 LIST => qr/^([-+]+)\s*(.+)/,
8 17     17   98 };
  17         37  
9              
10             sub parse {
11 328     328 0 527 my ($class, $s, $parent, $stack) = @_;
12              
13 328 100       1021 if ($s->scan(LIST)) {
14 18         67 my $node = $class->new([ $s->matched ]);
15 18   100     108 until ($s->eos || !$s->scan(LIST)) {
16 30         946 push @$node, $s->matched;
17             }
18 18         748 push @$parent, $node;
19 18         124 return 1;
20             }
21             }
22              
23             sub as_struct {
24 15     15 0 25 my ($self) = @_;
25              
26 15         25 my $ret = [];
27 15         23 my $stack = []; # ol ul stack (that is, exluding li)
28              
29 15         23 for my $child (@{ $self->children }) {
  15         62  
30 39         70 my ($line, $symbol, $text) = @$child;
31 39         47 my $level = length($symbol);
32 39 100       115 my $type = substr($line, $level - 1, 1) eq '+' ? 'ol' : 'ul';
33              
34 39         95 while ($level < @$stack) {
35 3         9 pop @$stack;
36             }
37              
38 39 100 100     154 pop @$stack if @$stack == $level && $stack->[-1]->{name} ne $type;
39              
40 39         92 while (@$stack < $level) {
41 23         81 my $container = +{
42             name => $type,
43             items => []
44             };
45              
46 23 100       55 if (@$stack) {
47 7 100       17 if ($stack->[-1]->{items}->[-1]) {
48 3         3 push @{ $stack->[-1]->{items}->[-1]->{children} }, $container;
  3         7  
49             } else {
50 4         12 my $item = {
51             name => 'li',
52             children => [ $container ],
53             };
54 4         4 push @{ $stack->[-1]->{items} }, $item;
  4         9  
55             }
56             } else {
57 16         30 push @$ret, $container;
58             }
59 23         59 push @$stack, $container;
60             }
61              
62 39         136 my $item = {
63             name => 'li',
64             children => [ $text ],
65             };
66              
67 39         46 push @{ $stack->[-1]->{items} }, $item;
  39         109  
68             }
69              
70 15         96 $ret;
71             }
72              
73             sub as_html {
74 15     15 0 39 my ($self, $context, %opts) = @_;
75 15         21 my $ret = '';
76 15         23 for my $list (@{ $self->as_struct }) {
  15         40  
77 16         54 $ret .= $self->_as_html($context, $list, %opts);
78             }
79 15         107 $ret;
80             }
81              
82             sub _as_html {
83 23     23   52 my ($self, $context, $list, %opts) = @_;
84              
85             $context->_tmpl(__PACKAGE__, q[
86             <{{= $name }}>
87             ? for (@$items) {
88            
  • {{= $_ }}
  • 89             ? }
    90            
    91             ], {
    92             name => $list->{name},
    93             items => [
    94             map {
    95 23         41 join('',
    96             map {
    97 46 100       82 if (ref($_)) {
      43         81  
    98 7         20 $self->_as_html($context, $_, %opts)
    99             } else {
    100 39         94 $context->inline->format($_)
    101             }
    102             }
    103 43         52 @{ $_->{children} }
    104             )
    105             }
    106 23         42 @{ $list->{items} }
    107             ]
    108             });
    109             }
    110              
    111              
    112             1;
    113             __END__