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.04';
4              
5 1     1   1372 use strict;
  1         7  
  1         24  
6 1     1   3 use warnings;
  1         2  
  1         19  
7              
8 1     1   15 use v5.20;
  1         3  
9              
10 1     1   11 use feature 'signatures';
  1         2  
  1         138  
11 1     1   5 no warnings 'experimental::signatures';
  1         7  
  1         29  
12              
13 1     1   294 use Pod::Headings;
  1         3  
  1         31  
14 1     1   346 use Pod::Definitions::Heuristic;
  1         2  
  1         374  
15              
16             #
17             #
18             #
19 2     2 1 624 sub new ($class, @args) {
  2         3  
  2         3  
  2         3  
20 2         3 my $self = {@args};
21 2         4 bless $self, $class;
22              
23 2         5 return $self;
24             }
25              
26             #
27             # Accessors
28             #
29              
30 2     2 1 1097 sub file ($self) { return $self->{file}; } # Local path to file
  2         4  
  2         2  
  2         10  
31 8     8 1 8 sub manpage ($self) { return $self->{manpage}; } # Full name of manpage ('Mojo::Path')
  8         8  
  8         6  
  8         18  
32 2     2 1 3 sub module ($self) { return $self->{module}; } # Module leaf name ('Path')
  2         3  
  2         2  
  2         7  
33 7     7 1 7 sub sections ($self, $section = undef) {
  7         7  
  7         8  
  7         7  
34             return defined $section ?
35             $self->{sections}->{$section} : # Array of entries in that section, or undef
36 7 100       365 $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         10  
  6         7  
43 6         15 $human_text =~ s/(\s|\(|=|\[)/-/g;
44 6         19 $human_text =~ s/([^a-zA-Z0-9_\-*:])//g;
45 6         55 return $human_text;
46             }
47              
48 6     6   5 sub _save_definition ($self, $parser, $attrs, $head1, $text) {
  6         6  
  6         6  
  6         4  
  6         5  
  6         7  
  6         5  
49 6         16 my $cooked_heading = Pod::Definitions::Heuristic->new(text => $text);
50 6         16 push @{$self->{sections}{$head1}}, {raw => $text,
51             cooked => $cooked_heading->clean,
52             sequence => $attrs->{sequence},
53 6         6 link => $self->manpage(),
54             link_fragment => convert_to_href_text($text),
55             };
56             }
57              
58 2     2   7 sub _save_file_manpage ($self, $text) {
  2         3  
  2         3  
  2         3  
59 2 50       12 $self->{manpage} = $text unless defined $self->{manpage};
60             }
61              
62 2     2   32 sub _save_file_module_leaf ($self, $text) {
  2         4  
  2         2  
  2         3  
63 2         4 $self->{module} = $text;
64             }
65              
66 2     2   3 sub _save_module_name ($self, $parser, $elem, $attrs, $text) {
  2         2  
  2         3  
  2         2  
  2         2  
  2         2  
  2         3  
67 2         8 $text =~ m/^\s*(?\S+)/;
68 1     1   429 my $module_name = $+{module_name};
  1         373  
  1         215  
  2         15  
69 2         7 $self->_save_file_manpage($module_name);
70             # "Mojo::Log" → index under last component: "Log"
71 2         9 $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         2  
  2         2  
  2         2  
75 2         4 $self->{version} = $text;
76             }
77              
78 2     2   2 sub _save_see_also ($self, $parser, $elem, $attrs, $text) {
  2         3  
  2         2  
  2         3  
  2         3  
  2         2  
  2         2  
79 2         3 push @{$self->{see_also}}, $text;
  2         5  
80             }
81              
82 2     2 1 796 sub parse_file ($self, $file, $podname = undef) {
  2         3  
  2         2  
  2         3  
  2         2  
83              
84 2         3 my $save_next;
85              
86 2         4 $self->{file} = $file;
87 2 50       5 $self->_save_file_manpage($podname) if defined $podname;
88              
89 15         10 return Pod::Headings->new(
90 15     15   13 head1 => sub ($parser, $elem, $attrs, $plaintext) {
  15         15  
  15         13  
  15         12  
  15         14  
91             # "Archive::Zip Methods" -> "Methods":
92 15 100       79 $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   516 if ($plaintext =~ /^[ \p{Uppercase}]{2,}/) {
  1         11  
  1         13  
  15         44  
97 15         85 $plaintext =~ s/^(.)(.*)/\u$1\L$2/;
98             }
99 15         29 $parser->{_save_head1} = $plaintext;
100 15         17 undef $parser->{_save_head2};
101 15         17 $parser->{_save_first_para} = 1;
102              
103 15 100       37 if (lc($plaintext) eq 'name') {
    100          
    100          
104 2         10 $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   5 head2 => sub ($parser, $elem, $attrs, $plaintext) {
  6         7  
  6         6  
  6         6  
  6         5  
  6         7  
116             # print " $elem: $parser->{_save_head1}: $plaintext\n";
117 6         8 $parser->{_save_head2} = $plaintext;
118 6         6 $parser->{_save_first_para} = 1;
119              
120 6         12 $self->_save_definition ( $parser, $attrs, $parser->{_save_head1}, $plaintext );
121              
122 6         14 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 28     28   30 Para => sub ($parser, $elem, $attrs, $plaintext) {
  28         27  
  28         25  
  28         22  
  28         26  
  28         25  
130 28 100       44 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         18 undef $save_next;
134             }
135 28         33 $parser->{_save_first_para} = 0;
136 28         38 1;
137             },
138 2         26 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__