File Coverage

lib/Pod/Definitions.pm
Criterion Covered Total %
statement 152 160 95.0
branch 17 20 85.0
condition n/a
subroutine 25 26 96.1
pod 6 7 85.7
total 200 213 93.9


line stmt bran cond sub pod time code
1             package Pod::Definitions;
2              
3             our $VERSION = '0.03';
4              
5 1     1   1359 use strict;
  1         6  
  1         24  
6 1     1   3 use warnings;
  1         2  
  1         19  
7              
8 1     1   16 use v5.20;
  1         3  
9              
10 1     1   5 use feature 'signatures';
  1         1  
  1         141  
11 1     1   5 no warnings 'experimental::signatures';
  1         2  
  1         44  
12              
13 1     1   297 use Pod::Headings;
  1         3  
  1         35  
14 1     1   370 use Pod::Definitions::Heuristic;
  1         2  
  1         356  
15              
16             #
17             #
18             #
19 2     2 1 635 sub new ($class, @args) {
  2         4  
  2         3  
  2         3  
20 2         4 my $self = {@args};
21 2         2 bless $self, $class;
22              
23 2         5 return $self;
24             }
25              
26             #
27             # Accessors
28             #
29              
30 2     2 1 1266 sub file ($self) { return $self->{file}; } # Local path to file
  2         3  
  2         4  
  2         10  
31 8     8 1 9 sub manpage ($self) { return $self->{manpage}; } # Full name of manpage ('Mojo::Path')
  8         37  
  8         8  
  8         20  
32 2     2 1 4 sub module ($self) { return $self->{module}; } # Module leaf name ('Path')
  2         2  
  2         3  
  2         7  
33 7     7 1 8 sub sections ($self, $section = undef) {
  7         6  
  7         9  
  7         6  
34             return defined $section ?
35             $self->{sections}->{$section} : # Array of entries in that section, or undef
36 7 100       33 $self->{sections}; # Hash (key=toplevel section) of arrays of section names
37             }
38             #
39             #
40             #
41              
42 6     6 0 5 sub convert_to_href_text ($human_text) {
  6         7  
  6         6  
43 6         18 $human_text =~ s/(\s|\(|=|\[)/-/g;
44 6         9 $human_text =~ s/([^a-zA-Z0-9_\-*:])//g;
45 6         32 return $human_text;
46             }
47              
48 6     6   5 sub _save_definition ($self, $parser, $attrs, $head1, $text) {
  6         4  
  6         5  
  6         6  
  6         7  
  6         6  
  6         6  
49 6         17 my $cooked_heading = Pod::Definitions::Heuristic->new(text => $text);
50 6         17 push @{$self->{sections}{$head1}}, {raw => $text,
51             cooked => $cooked_heading->clean,
52             sequence => $attrs->{sequence},
53 6         7 link => $self->manpage(),
54             link_fragment => convert_to_href_text($text),
55             };
56             }
57              
58 2     2   2 sub _save_file_manpage ($self, $text) {
  2         3  
  2         3  
  2         2  
59 2 50       8 $self->{manpage} = $text unless defined $self->{manpage};
60             }
61              
62 2     2   34 sub _save_file_module_leaf ($self, $text) {
  2         4  
  2         3  
  2         2  
63 2         7 $self->{module} = $text;
64             }
65              
66 2     2   2 sub _save_module_name ($self, $parser, $elem, $attrs, $text) {
  2         3  
  2         13  
  2         3  
  2         2  
  2         3  
  2         1  
67 2         8 $text =~ m/^\s*(?\S+)/;
68 1     1   401 my $module_name = $+{module_name};
  1         360  
  1         227  
  2         19  
69 2         17 $self->_save_file_manpage($module_name);
70             # "Mojo::Log" → index under last component: "Log"
71 2         24 $self->_save_file_module_leaf( (split /::/, $module_name)[-1] );
72             }
73              
74 2     2   3 sub _save_version ($self, $parser, $elem, $attrs, $text) {
  2         2  
  2         3  
  2         2  
  2         4  
  2         2  
  2         1  
75 2         6 $self->{version} = $text;
76             }
77              
78 2     2   2 sub _save_see_also ($self, $parser, $elem, $attrs, $text) {
  2         2  
  2         3  
  2         2  
  2         3  
  2         2  
  2         3  
79 2         2 push @{$self->{see_also}}, $text;
  2         6  
80             }
81              
82 2     2 1 867 sub parse_file ($self, $file, $podname = undef) {
  2         4  
  2         3  
  2         2  
  2         2  
83              
84 2         2 my $save_next;
85              
86 2         6 $self->{file} = $file;
87 2 50       6 $self->_save_file_manpage($podname) if defined $podname;
88              
89 15         14 return Pod::Headings->new(
90 15     15   14 head1 => sub ($parser, $elem, $attrs, $plaintext) {
  15         14  
  15         14  
  15         10  
  15         15  
91             # "Archive::Zip Methods" -> "Methods":
92 15 100       76 $plaintext =~ s/^($self->{manpage}\s+)//i if defined $self->{manpage};
93             # Change headings starting in all-uppercase to inital caps
94             # only. Note, "READING CPAN.pm" -> "Reading cpan.pm"
95             # (there is only so much we can do without A.I.)
96 1 50   1   528 if ($plaintext =~ /^[ \p{Uppercase}]{2,}/) {
  1         12  
  1         11  
  15         69  
97 15         90 $plaintext =~ s/^(.)(.*)/\u$1\L$2/;
98             }
99 15         29 $parser->{_save_head1} = $plaintext;
100 15         17 undef $parser->{_save_head2};
101 15         16 $parser->{_save_first_para} = 1;
102              
103 15 100       45 if (lc($plaintext) eq 'name') {
    100          
    100          
104 2         4 $save_next = \&_save_module_name;
105             } elsif (lc($plaintext) eq 'version') {
106 2         3 $save_next = \&_save_version;
107             } elsif (lc($plaintext) eq 'see also') {
108 2         4 $save_next = \&_save_see_also;
109             } else {
110 9         10 undef $save_next;
111             }
112              
113 15         31 1;
114             },
115 6     6   6 head2 => sub ($parser, $elem, $attrs, $plaintext) {
  6         4  
  6         6  
  6         7  
  6         5  
  6         7  
116             # print " $elem: $parser->{_save_head1}: $plaintext\n";
117 6         7 $parser->{_save_head2} = $plaintext;
118 6         7 $parser->{_save_first_para} = 1;
119              
120 6         14 $self->_save_definition ( $parser, $attrs, $parser->{_save_head1}, $plaintext );
121              
122 6         13 1;
123             },
124 0     0   0 head3 => sub ($parser, $elem, $attrs, $plaintext) {
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
125             # print " $elem: $parser->{_save_head1} / $parser->{_save_head2}: $plaintext\n";
126 0         0 $self->_save_definition ( $parser, $attrs, $parser->{_save_head2}, $plaintext );
127 0         0 1;
128             },
129 23     23   19 Para => sub ($parser, $elem, $attrs, $plaintext) {
  23         21  
  23         24  
  23         23  
  23         20  
  23         23  
130 23 100       32 if ($parser->{_save_first_para}) {
131             # print " .... text: $plaintext\n";
132 18 100       33 $self->$save_next($parser, $elem, $attrs, $plaintext) if defined $save_next;
133 18         20 undef $save_next;
134             }
135 23         25 $parser->{_save_first_para} = 0;
136 23         34 1;
137             },
138 2         35 L => 1, # Return 0 to drop the plaintext passed to the containing element
139             # Possible extension: In 'See Also' sections, accumulate the
140             # actual links from Pod::Simple in the same form with (raw, cooked, link)
141             )->parse_file($file);
142             }
143              
144             1;
145              
146             __END__