File Coverage

blib/lib/App/podman/Parser/Pod.pm
Criterion Covered Total %
statement 75 84 89.2
branch 26 28 92.8
condition 1 3 33.3
subroutine 13 14 92.8
pod 1 4 25.0
total 116 133 87.2


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2021 -- leonerd@leonerd.org.uk
5              
6 3     3   80349 use v5.26;
  3         21  
7              
8 3     2   679 use Object::Pad 0.41;
  2         10816  
  2         13  
9              
10             package App::podman::Parser::Pod 0.01;
11             class App::podman::Parser::Pod
12             isa Pod::Simple
13 2     2   1667 does App::podman::Parser;
  2         68256  
  2         159  
14              
15 2     2   1716 use List::Keywords qw( any );
  2         2051  
  2         15  
16 2     2   125 use List::Util qw( min );
  2         4  
  2         249  
17              
18 2     2   15 use String::Tagged;
  2         4  
  2         90  
19              
20 2     2   12 use constant format => "POD";
  2         3  
  2         4784  
21              
22 2         5 sub can_parse_file ( $class, $file )
23 2     2 0 761 {
  2         4  
  2         4  
24 2         25 return $file =~ m/\.pm$|\.pod$/;
25             }
26              
27             BUILD
28             {
29             $self->nix_X_codes( 1 );
30             }
31              
32             has @_parastack;
33              
34             has %_curtags;
35             has $_curpara;
36              
37 0         0 method parse_file ( $fh )
  0         0  
  0         0  
38 0     0 1 0 {
39 0         0 push @_parastack, [];
40 0         0 $self->SUPER::parse_file( $fh );
41 0         0 return $_parastack[0]->@*;
42             }
43              
44 6         24 method parse_string ( $str )
  6         15  
  6         10  
45 6     6 0 115 {
46 6         28 push @_parastack, [];
47 6         36 $self->SUPER::parse_string_document ( $str );
48 6         96 return $_parastack[0]->@*;
49             }
50              
51             my %PARA_TYPES = (
52             Para => "App::podman::Para::Plain",
53             Verbatim => "App::podman::Para::Verbatim",
54             );
55             my @FORMAT_TYPES = qw( B I F C L );
56              
57 40         68 method _handle_element_start ($type, $attrs)
  40         66  
  40         51  
  40         53  
58 40     40   9958 {
59 40 100       216 if( $type eq "Document" ) {
    100          
    100          
    100          
    100          
    100          
    50          
60 6         33 %_curtags = ();
61             }
62             elsif( $type =~ m/^head(\d+)$/ ) {
63 3         27 push $_parastack[-1]->@*, $_curpara = App::podman::Para::Heading->new(
64             level => $1,
65             text => String::Tagged->new,
66             );
67 3         122 %_curtags = ();
68             }
69             elsif( my $class = $PARA_TYPES{$type} ) {
70 10         45 push $_parastack[-1]->@*, $_curpara = $class->new(
71             text => String::Tagged->new,
72             );
73 10         316 %_curtags = ();
74             }
75             elsif( $type eq "L" ) {
76 1         28 $_curtags{L} = { target => $attrs->{to} };
77             }
78 79         209 elsif( any { $type eq $_ } @FORMAT_TYPES ) {
79 8         26 ++$_curtags{$type};
80             }
81             elsif( $type =~ m/^over-(.*)/ ) {
82             push $_parastack[-1]->@*, App::podman::Para::List->new(
83             listtype => $1,
84             indent => $attrs->{indent},
85 3         41 );
86 3         68 push @_parastack, [];
87 3         13 undef $_curpara;
88             }
89             elsif( $type =~ m/^item-(.*)/ ) {
90 9         41 push @_parastack[-1]->@*, $_curpara = App::podman::Para::ListItem->new(
91             text => String::Tagged->new,
92             );
93             }
94             else {
95 0         0 print STDERR "START $_[0]\n";
96             }
97             }
98              
99 40         55 method _handle_element_end ($type, @)
  40         57  
  40         53  
100 40     40   1972 {
101 40 100       157 if( $type eq "Document" ) {
    100          
    100          
    100          
    100          
    50          
102             # nothing
103             }
104             elsif( $type =~ m/^head\d+$/ ) {
105             # nothing
106             }
107             elsif( $PARA_TYPES{$type} ) {
108 10 100       42 $type eq "Verbatim" and
109             $_parastack[-1][-1] = $self->trim_leading_whitespace( $_parastack[-1][-1] );
110             }
111 84         217 elsif( any { $type eq $_ } @FORMAT_TYPES ) {
112 9         29 delete $_curtags{$type};
113             }
114             elsif( $type =~ m/^over-(.*)/ ) {
115 3         13 my @items = ( pop @_parastack )->@*;
116 3         25 $_parastack[-1][-1]->push_item( $_ ) for @items;
117             }
118             elsif( $type =~ m/^item-.*/ ) {
119             # nothing
120             }
121             else {
122 0         0 print STDERR "END $_[0]\n";
123             }
124             }
125              
126             method _handle_text
127 32     32   638 {
128 32         94 $_curpara->text->append_tagged( $_[0], %_curtags );
129             }
130              
131 1         3 method trim_leading_whitespace ( $para )
  1         2  
  1         3  
132 1     1 0 3 {
133 1         5 my @lines = $para->text->split( qr/\n/ );
134              
135 1         118 my $trimlen = min map { m/^(\s*)/; $+[1] } grep { length } @lines;
  3         12  
  3         25  
  3         14  
136              
137 1   33     6 length and $_ = $_->substr( $trimlen, length $_ ) for @lines;
138              
139 1         80 my $text = shift @lines;
140 1         6 $text .= "\n" . $_ for @lines;
141              
142 1         381 return (ref $para)->new(
143             text => $text,
144             );
145             }
146              
147             0x55AA;