File Coverage

blib/lib/Pod/Thread.pm
Criterion Covered Total %
statement 339 344 98.5
branch 86 100 86.0
condition 23 32 71.8
subroutine 55 55 100.0
pod 1 1 100.0
total 504 532 94.7


line stmt bran cond sub pod time code
1             # Convert POD data to the HTML macro language thread.
2             #
3             # This module converts POD to the HTML macro language thread. It's intended
4             # for use with the spin program to include POD documentation in a
5             # spin-generated web page complex.
6             #
7             # SPDX-License-Identifier: MIT
8              
9             ##############################################################################
10             # Modules and declarations
11             ##############################################################################
12              
13             package Pod::Thread 3.00;
14              
15 1     1   116845 use 5.024;
  1         11  
16 1     1   5 use strict;
  1         2  
  1         19  
17 1     1   5 use warnings;
  1         2  
  1         26  
18              
19 1     1   4 use base qw(Pod::Simple);
  1         2  
  1         744  
20              
21 1     1   32662 use Carp qw(croak);
  1         3  
  1         49  
22 1     1   6 use Encode qw(encode);
  1         2  
  1         40  
23 1     1   776 use Text::Balanced qw(extract_bracketed);
  1         17711  
  1         85  
24 1     1   552 use Text::Wrap qw(wrap);
  1         2763  
  1         4917  
25              
26             # Pod::Simple uses subroutines named as if they're private for subclassing,
27             # and we dynamically construct method names on the fly.
28             ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
29              
30             ##############################################################################
31             # Internal constants
32             ##############################################################################
33              
34             # Regex matching a manpage-style entry in the NAME header. $1 is set to the
35             # list of things documented by the man page, and $2 is set to the description.
36             my $NAME_REGEX = qr{ \A ( \S+ (?:,\s*\S+)* ) [ ] - [ ] (.*) }xms;
37              
38             # Maximum length of each line when constructing a navbar.
39             my $NAVBAR_LENGTH = 65;
40              
41             # Margin at which to wrap thread output.
42             my $WRAP_MARGIN = 75;
43              
44             ##############################################################################
45             # Initialization
46             ##############################################################################
47              
48             # Initialize the object and set various Pod::Simple options that we need.
49             # Here, we also process any additional options passed to the constructor or
50             # set up defaults if none were given. Note that all internal object keys are
51             # in all-caps, reserving all lower-case object keys for Pod::Simple and user
52             # arguments. User options are rewritten to start with opt_ to avoid conflicts
53             # with Pod::Simple.
54             #
55             # %opts - Our options as key/value pairs
56             #
57             # Returns: Newly constructed Pod::Thread object
58             # Throws: Whatever Pod::Simple's constructor might throw
59             sub new {
60 18     18 1 30244 my ($class, %opts) = @_;
61 18         79 my $self = $class->SUPER::new;
62              
63             # Tell Pod::Simple to handle S<> by automatically inserting E.
64 18         450 $self->nbsp_for_S(1);
65              
66             # The =for and =begin targets that we accept.
67 18         161 $self->accept_targets('thread');
68              
69             # Ensure that contiguous blocks of code are merged together.
70 18         286 $self->merge_text(1);
71              
72             # Preserve whitespace whenever possible to make debugging easier.
73 18         111 $self->preserve_whitespace(1);
74              
75             # Always send errors to standard error.
76 18         112 $self->no_errata_section(1);
77 18         100 $self->complain_stderr(1);
78              
79             # Pod::Simple doesn't do anything useful with our arguments, but we want
80             # to put them in our object as hash keys and values. This could cause
81             # problems if we ever clash with Pod::Simple's own internal class
82             # variables, so rename them with an opt_ prefix.
83 18         119 my @opts = map { ("opt_$_", $opts{$_}) } keys %opts;
  29         110  
84 18         34 %{$self} = (%{$self}, @opts);
  18         85  
  18         57  
85              
86 18         67 return $self;
87             }
88              
89             ##############################################################################
90             # Core parsing
91             ##############################################################################
92              
93             # This is the glue that connects the code below with Pod::Simple itself. The
94             # goal is to convert the event stream coming from the POD parser into method
95             # calls to handlers once the complete content of a tag has been seen. Each
96             # paragraph or POD command will have textual content associated with it, and
97             # as soon as all of a paragraph or POD command has been seen, that content
98             # will be passed in to the corresponding method for handling that type of
99             # object. The exceptions are handlers for lists, which have opening tag
100             # handlers and closing tag handlers that will be called right away.
101             #
102             # The internal hash key PENDING is used to store the contents of a tag until
103             # all of it has been seen. It holds a stack of open tags, each one
104             # represented by a tuple of the attributes hash for the tag and the contents
105             # of the tag.
106              
107             # Add a block of text to the contents of the current node, protecting any
108             # thread metacharacters unless we're in a literal (=for or =begin) block.
109             #
110             # $text - A block of ordinary text seen in the POD
111             sub _handle_text {
112 101     101   845 my ($self, $text) = @_;
113 101 100       220 if (!$self->{LITERAL}) {
114 97         203 $text =~ s{ \\ }{\\\\}xmsg;
115 97         197 $text =~ s{ ([\[\]]) }{'\\entity[' . ord($1) . ']'}xmseg;
  8         34  
116             }
117 101         150 my $tag = $self->{PENDING}[-1];
118 101         181 $tag->[1] .= $text;
119 101         195 return;
120             }
121              
122             # Given an element name, get the corresponding portion of a method name. The
123             # real methods will be formed by prepending cmd_, start_, or end_.
124             #
125             # $element - Name of the POD element by Pod::Simple's naming scheme.
126             #
127             # Returns: The element transformed into part of a method name.
128             sub _method_for_element {
129 254     254   389 my ($self, $element) = @_;
130 254         362 $element =~ tr{-}{_};
131 254         364 $element =~ tr{A-Z}{a-z};
132 254         370 $element =~ tr{_a-z0-9}{}cd;
133 254         462 return $element;
134             }
135              
136             # Handle the start of a new element. If cmd_element is defined, assume that
137             # we need to collect the entire tree for this element before passing it to the
138             # element method, and create a new tree into which we'll collect blocks of
139             # text and nested elements. Otherwise, if start_element is defined, call it.
140             #
141             # $element - The name of the POD element that was started
142             # $attrs - The attribute hash for that POD element.
143             sub _handle_element_start {
144 127     127   44816 my ($self, $element, $attrs) = @_;
145 127         265 my $method = $self->_method_for_element($element);
146              
147             # If we have a command handler, we need to accumulate the contents of the
148             # tag before calling it. If we have a start handler, call it immediately.
149 127 100       694 if ($self->can("_cmd_$method")) {
    50          
150 96         241 push($self->{PENDING}->@*, [$attrs, q{}]);
151             } elsif ($self->can("_start_$method")) {
152 31         78 $method = '_start_' . $method;
153 31         91 $self->$method($attrs, q{});
154             }
155 127         281 return;
156             }
157              
158             # Handle the end of an element. If we had a cmd_ method for this element,
159             # this is where we pass along the text that we've accumulated. Otherwise, if
160             # we have an end_ method for the element, call that.
161             #
162             # $element - The name of the POD element that was started
163             sub _handle_element_end {
164 127     127   2257 my ($self, $element) = @_;
165 127         209 my $method = $self->_method_for_element($element);
166              
167             # If we have a command handler, pull off the pending text and pass it to
168             # the handler along with the saved attribute hash. Otherwise, if we have
169             # an end method, call it.
170 127 100       472 if ($self->can("_cmd_$method")) {
    50          
171 96         176 my $tag_ref = pop($self->{PENDING}->@*);
172 96         180 $method = '_cmd_' . $method;
173 96         256 my $text = $self->$method($tag_ref->@*);
174              
175             # If the command returned some text, check if the element stack is
176             # non-empty. If so, add that text to the next open element.
177             # Otherwise, we're at the top level and can output the text directly.
178 96 100       201 if (defined($text)) {
179 20 50       39 if ($self->{PENDING}->@* > 1) {
180 20         54 $self->{PENDING}[-1][1] .= $text;
181             } else {
182 0         0 $self->_output($text);
183             }
184             }
185 96         219 return;
186             } elsif ($self->can("_end_$method")) {
187 31         58 $method = '_end_' . $method;
188 31         73 return $self->$method();
189             } else {
190 0         0 return;
191             }
192             }
193              
194             ##############################################################################
195             # Output formatting
196             ##############################################################################
197              
198             # Ensure text ends in two newlines.
199             #
200             # $text - Text to reformat
201             #
202             # Returns: Text with whitespace fixed
203             sub _reformat {
204 32     32   56 my ($self, $text) = @_;
205 32         236 $text =~ s{ \s* \z }{\n\n}xms;
206 32         97 return $text;
207             }
208              
209             # Accumulate output text. We may have some accumulated whitespace in the
210             # SPACE internal variable; if so, add that after any closing bracket at the
211             # start of our output. Then, save any whitespace at the end of our output and
212             # defer it for next time. (This creates much nicer association of closing
213             # brackets.)
214             #
215             # $text - Text to output
216             sub _output {
217 98     98   183 my ($self, $text) = @_;
218              
219             # If we have deferred whitespace, output it before the text, but after any
220             # closing bracket at the start of the text.
221 98 100       192 if ($self->{SPACE}) {
222 61 100       202 if ($text =~ s{ \A \] \s* \n }{}xms) {
223 11         21 $self->{OUTPUT} .= "]\n";
224             }
225 61         149 $self->{OUTPUT} .= $self->{SPACE};
226 61         103 undef $self->{SPACE};
227             }
228              
229             # Defer any trailing newlines beyond a single newline.
230 98 100       348 if ($text =~ s{ \n (\n+) \z }{\n}xms) {
231 61         203 $self->{SPACE} = $1;
232             }
233              
234             # Append the text to the output.
235 98         185 $self->{OUTPUT} .= $text;
236 98         196 return;
237             }
238              
239             # Flush the output at the end of a document by sending it to the correct
240             # output file handle. Force the encoding to UTF-8 unless we've found that we
241             # already have a UTF-8 encoding layer.
242             sub _flush_output {
243 18     18   26 my ($self) = @_;
244 18         32 my $output = $self->{OUTPUT};
245              
246             # Encode if necessary and then output.
247 18 50       37 if ($self->{ENCODE}) {
248 18         31 $output = encode('UTF-8', $output);
249             }
250 18 50       718 print { $self->{output_fh} } $output
  18         62  
251             or die "Cannot write to output: $!\n";
252              
253             # Clear the output to avoid sending it twice.
254 18         156 $self->{OUTPUT} = q{};
255 18         27 return;
256             }
257              
258             ##############################################################################
259             # Document start and finish
260             ##############################################################################
261              
262             # Construct a table of contents from the headings seen throughout the
263             # document.
264             #
265             # Returns: The thread code for the table of contents
266             sub _contents {
267 5     5   20 my ($self) = @_;
268 5 100       18 return q{} if !$self->{HEADINGS}->@*;
269              
270             # Construct and return the table of contents.
271 4         8 my $output = "\\h2[Table of Contents]\n\n";
272 4         11 for my $i (0 .. $self->{HEADINGS}->$#*) {
273 9         16 my $tag = 'S' . ($i + 1);
274 9         14 my $section = $self->{HEADINGS}[$i];
275 9         26 $output .= "\\number(packed)[\\link[#$tag][$section]]\n";
276             }
277 4         6 $output .= "\n";
278 4         10 return $output;
279             }
280              
281             # Capitalize a heading for the navigation bar. Normally we want to use
282             # title case, but don't lowercase elements containing an underscore.
283             #
284             # $heading - The heading to capitalize
285             #
286             # Returns: The properly capitalized heading.
287             sub _capitalize_for_navbar {
288 11     11   55 my ($self, $heading) = @_;
289 11         57 my @words = split(m{ (\s+) }xms, $heading);
290 11         21 for my $word (@words) {
291 63 100 100     293 if ($word !~ m{ _ }xms && $word !~ m{ \A \\ }xms) {
292 57         77 $word = lc($word);
293 57 100       99 if ($word ne 'and') {
294 55         85 $word = ucfirst($word);
295             }
296             }
297             }
298 11         40 return join(q{}, @words);
299             }
300              
301             # Construct a navigation bar. This is like a table of contents, but lists the
302             # sections separated by vertical bars and tries to limit the number of
303             # sections per line. The navbar will be presented in the sorted order of the
304             # tags.
305             #
306             # Returns: The thread code for the navbar
307             sub _navbar {
308 5     5   8 my ($self) = @_;
309 5 50       14 return if !$self->{HEADINGS}->@*;
310              
311             # Build the start of the navbar.
312 5         7 my $output = "\\class(navbar)[\n ";
313              
314             # Format the navigation bar, accumulating each line in $output. Store the
315             # formatted length in $length. We can't use length($output) because that
316             # would count all the thread commands. This won't be quite right if
317             # headings contain formatting.
318 5         22 my $pending = q{};
319 5         7 my $length = 0;
320 5         17 for my $i (0 .. scalar($self->{HEADINGS}->$#*)) {
321 11         19 my $tag = 'S' . ($i + 1);
322 11         18 my $section = $self->{HEADINGS}[$i];
323              
324             # If adding this section would put us over 60 characters, output the
325             # current line with a line break.
326 11 100 100     39 if ($length > 0 && $length + length($section) > $NAVBAR_LENGTH) {
327 1         5 $output .= "$pending\\break\n ";
328 1         2 $pending = q{};
329 1         2 $length = 0;
330             }
331              
332             # If this isn't the first thing on a line, add the separator.
333 11 100       22 if (length($pending) != 0) {
334 5         9 $pending .= q{ | };
335 5         8 $length += length(q{ | });
336             }
337              
338             # Convert the section names to titlecase.
339 11         21 my $name = $self->_capitalize_for_navbar($section);
340              
341             # Add it to the current line.
342 11         29 $pending .= "\\link[#$tag][$name]\n";
343 11         25 $length += length($name);
344             }
345              
346             # Collect any remaining partial line and the end of the navbar.
347 5 50       11 if (length($pending) > 0) {
348 5         10 $output .= $pending;
349             }
350 5         8 $output .= "]\n\n";
351 5         11 return $output;
352             }
353              
354             # Construct the header and title of the document, including any navigation bar
355             # and contents section if we have any.
356             #
357             # $title - Document title
358             # $subheading - Document subheading (may be undef)
359             #
360             # Returns: The thread source for the document heading
361             sub _header {
362 18     18   26 my ($self) = @_;
363 18   50     68 my $style = $self->{opt_style} || q{};
364 18         24 my $output = q{};
365              
366             # Add the basic title, page heading, and style if we saw a title.
367 18 100       36 if ($self->{TITLE}) {
368 4         12 $output .= "\\heading[$self->{TITLE}][$style]\n\n";
369 4         11 $output .= "\\h1[$self->{TITLE}]\n\n";
370             }
371              
372             # If there is a subheading, add it.
373 18 100       33 if (defined($self->{SUBHEADING})) {
374 3         6 $output .= "\\class(subhead)[($self->{SUBHEADING})]\n\n";
375             }
376              
377             # If a navbar or table of contents was requested, add it.
378 18 100       35 if ($self->{opt_navbar}) {
379 5         12 $output .= $self->_navbar();
380             }
381 18 100       38 if ($self->{opt_contents}) {
382 5         11 $output .= $self->_contents();
383             }
384              
385             # Return the results.
386 18         47 return $output;
387             }
388              
389             # Handle the beginning of a POD file. We only output something if title is
390             # set, in which case we output the title and other header information at the
391             # beginning of the resulting output file.
392             #
393             # $attrs - Attributes of the start document tag
394             sub _start_document {
395 18     18   32 my ($self, $attrs) = @_;
396              
397             # If the document has no content, set the appropriate internal flag.
398 18 100       39 if ($attrs->{contentless}) {
399 1         3 $self->{CONTENTLESS} = 1;
400             } else {
401 17         25 delete $self->{CONTENTLESS};
402             }
403              
404             # Initialize per-document variables.
405 18         31 $self->{HEADINGS} = [];
406 18         27 $self->{IN_NAME} = 0;
407 18         28 $self->{ITEM_OPEN} = 0;
408 18         25 $self->{ITEM_PENDING} = 0;
409 18         27 $self->{ITEMS} = [];
410 18         28 $self->{LITERAL} = 0;
411 18         30 $self->{OUTPUT} = q{};
412 18         33 $self->{PENDING} = [[]];
413 18         32 $self->{SUBHEADING} = undef;
414 18   100     69 $self->{TITLE} = $self->{opt_title} // q{};
415              
416             # Check whether our output file handle already has a PerlIO encoding layer
417             # set. If it does not, we'll need to encode our output before printing
418             # it. Wrap the check in an eval to handle versions of Perl without
419             # PerlIO.
420 18         38 $self->{ENCODE} = 1;
421 18         25 eval {
422 18         43 my @options = (output => 1, details => 1);
423 18         69 my @layers = PerlIO::get_layers($self->{output_fh}->**, @options);
424 18 50 33     62 if ($layers[-1] && ($layers[-1] & PerlIO::F_UTF8())) {
425 0         0 $self->{ENCODE} = 0;
426             }
427             };
428 18         27 return;
429             }
430              
431             # Canonicalize a heading for internal links. We run both the anchor text and
432             # the heading itself through this function so that whitespace differences
433             # don't cause us to fail to create the link.
434             #
435             # Note that this affects only the end-of-document rewriting, not the links we
436             # create as we go, because this case is rare and doing it as we go would
437             # require more state tracking.
438             #
439             # $heading - Text of heading
440             #
441             # Returns: Canonicalized heading text
442             sub _canonicalize_heading {
443 23     23   38 my ($self, $heading) = @_;
444 23         87 $heading =~ s{ \s+ }{ }xmsg;
445 23         96 return $heading;
446             }
447              
448             # Handle the end of the document. Tack \signature onto the end, output the
449             # header and the accumulated output, and die if we saw any errors.
450             #
451             # Throws: Text exception if there were any errata
452             sub _end_document {
453 18     18   26 my ($self) = @_;
454              
455             # Output the \signature command if we saw any content.
456 18 100       44 if (!$self->{CONTENTLESS}) {
457 17         25 $self->_output("\\signature\n");
458             }
459              
460             # Search for any unresolved links and try to fix their anchors. If we
461             # never saw the heading in question, remove the \link command. We have to
462             # use Text::Balanced and substr surgery to extract the anchor text since
463             # it may contain arbitrary markup.
464             #
465             # This is very inefficient for large documents, but I doubt anything
466             # processed by this module will be large enough to matter.
467 18         26 my $i = 1;
468 18         23 my $search = '\\link[#PLACEHOLDER]';
469 18         23 my $start = 0;
470 18         35 my %headings = map { ('[' . $self->_canonicalize_heading($_) . ']', $i++) }
471 18         42 $self->{HEADINGS}->@*;
472 18         70 while (($start = index($self->{OUTPUT}, $search, $start)) != -1) {
473 5         14 my $text = substr($self->{OUTPUT}, $start + length($search));
474 5         18 my ($anchor) = extract_bracketed($text, '[]', undef);
475 5         1001 my $heading;
476 5 50       12 if ($anchor) {
477 5         12 $heading = $self->_canonicalize_heading($anchor);
478             }
479              
480             # If this is a known heading, replace #PLACEHOLDER with the link to
481             # that heading and continue processing with the anchor text.
482             # Otherwise, replace the entire \link command with the anchor text and
483             # continue processing after it.
484 5 100 66     24 if (defined($anchor) && defined($headings{$heading})) {
485 4         5 $start += length('\\link[');
486 4         12 my $link = "#S$headings{$heading}";
487 4         20 substr($self->{OUTPUT}, $start, length('#PLACEHOLDER'), $link);
488             } else {
489 1         2 my $length = length('\\link[#PLACEHOLDER]') + length($anchor);
490 1         3 $anchor = substr($anchor, 1, -1);
491 1         3 substr($self->{OUTPUT}, $start, $length, $anchor);
492 1         4 $start += length($anchor);
493             }
494             }
495              
496             # Output the header.
497 18         38 my $header = $self->_header();
498 18 50       40 if ($self->{ENCODE}) {
499 18         50 $header = encode('UTF-8', $header);
500             }
501 18 50       1062 print { $self->{output_fh} } $header
  18         73  
502             or die "Cannot write to output: $!\n";
503              
504             # Flush the rest of the output.
505 18         192 $self->_flush_output();
506              
507             # Die if we saw any errors.
508 18 100       49 if ($self->any_errata_seen()) {
509 1         256 croak('POD document had syntax errors');
510             }
511 17         97 return;
512             }
513              
514             ##############################################################################
515             # Text blocks
516             ##############################################################################
517              
518             # Called for a regular text block. There are two tricky parts here. One is
519             # that if there is a pending item tag, we need to format this as an item
520             # paragraph. The second is that if we're in the NAME section and see the name
521             # and description of the page, we should print out the header.
522             #
523             # $attrs - Attributes for this command
524             # $text - The text of the block
525             sub _cmd_para {
526 31     31   60 my ($self, $attrs, $text) = @_;
527              
528             # Ensure the text block ends with a single newline.
529 31         116 $text =~ s{ \s+ \z }{\n}xms;
530              
531             # If we're inside an item block, handle this as an item.
532 31 100 66     41 if (@{ $self->{ITEMS} } > 0) {
  31 100       122  
533 8         17 $self->_item($self->_reformat($text));
534             }
535              
536             # If we're in the NAME section and see a line that looks like the special
537             # NAME section of a man page, stash that information for the page heading.
538             elsif ($self->{IN_NAME} && $text =~ $NAME_REGEX) {
539 3         14 my ($name, $description) = ($1, $2);
540 3         7 $self->{TITLE} = $name;
541 3         6 $self->{SUBHEADING} = $description;
542             }
543              
544             # Otherwise, this is a regular text block, so just output it with a
545             # trailing blank line.
546             else {
547 20         62 $self->_output($self->_reformat($text . "\n"));
548             }
549 31         55 return;
550             }
551              
552             # Called for a verbatim paragraph. The only trick is knowing whether to use
553             # the item method to handle it or just print it out directly.
554             #
555             # $attrs - Attributes for this command
556             # $text - The text of the block
557             sub _cmd_verbatim {
558 4     4   9 my ($self, $attrs, $text) = @_;
559              
560             # Ignore empty verbatim paragraphs.
561 4 50       18 if ($text =~ m{ \A \s* \z }xms) {
562 0         0 return;
563             }
564              
565             # Ensure the paragraph ends in a bracket and two newlines.
566 4         29 $text =~ s{ \s* \z }{\]\n\n}xms;
567              
568             # Pass the text to either item or output.
569 4 100       7 if (@{ $self->{ITEMS} } > 0) {
  4         12  
570 2         8 $self->_item("\\pre\n[$text");
571             } else {
572 2         8 $self->_output("\\pre\n[$text");
573             }
574 4         8 return;
575             }
576              
577             # Called for literal text produced by =for and similar constructs. Just
578             # output the text verbatim with cleaned-up whitespace.
579             #
580             # $attrs - Attributes for this command
581             # $text - The text of the block
582             sub _cmd_data {
583 4     4   9 my ($self, $attrs, $text) = @_;
584 4         13 $text =~ s{ \A (\s*\n)+ }{}xms;
585 4         23 $text =~ s{ \s* \z }{\n\n}xms;
586 4         9 $self->_output($text);
587 4         11 return;
588             }
589              
590             # Called when =for and similar constructs are started or ended. Set or clear
591             # the literal flag so that we won't escape the text on the way in.
592 2     2   4 sub _start_for { my ($self) = @_; $self->{LITERAL} = 1; return; }
  2         4  
  2         3  
593 2     2   3 sub _end_for { my ($self) = @_; $self->{LITERAL} = 0; return; }
  2         5  
  2         5  
594              
595             ##############################################################################
596             # Headings
597             ##############################################################################
598              
599             # The common code for handling all headings. Take care of any pending items
600             # or lists and then output the thread code for the heading.
601             #
602             # $text - The text of the heading itself
603             # $level - The level of the heading as a number (2..5)
604             # $tag - An optional tag for the heading
605             sub _heading {
606 22     22   50 my ($self, $text, $level, $tag) = @_;
607              
608             # If there is a waiting item or a pending close bracket, output it now.
609 22         53 $self->_finish_item();
610              
611             # Strip any trailing whitespace.
612 22         54 $text =~ s{ \s+ \z }{}xms;
613              
614             # Output the heading thread.
615 22 100       41 if (defined $tag) {
616 18         59 $self->_output("\\h$level($tag)[$text]\n\n");
617             } else {
618 4         15 $self->_output("\\h$level" . "[$text]\n\n");
619             }
620 22         47 return;
621             }
622              
623             # First level heading. This requires some special handling to update the
624             # IN_NAME setting based on whether we're currently in the NAME section. Also
625             # add a tag to the heading if we have section information.
626             #
627             # $attrs - Attributes for this command
628             # $text - The text of the block
629             #
630             # Returns: The result of the heading method
631             sub _cmd_head1 {
632 21     21   43 my ($self, $attrs, $text) = @_;
633              
634             # Strip whitespace from the text since we're going to compare it to other
635             # things.
636 21         57 $text =~ s{ \s+ \z }{}xms;
637              
638             # If we're in the NAME section and no title was explicitly set, set the
639             # flag used in cmd_para to parse the NAME text specially and then do
640             # nothing else (since we won't print out the NAME section as itself.
641 21 100 66     67 if ($text eq 'NAME' && !exists($self->{opt_title})) {
642 3         6 $self->{IN_NAME} = 1;
643 3         7 return;
644             }
645 18         31 $self->{IN_NAME} = 0;
646              
647             # Not in the name section. Record the heading and a tag to the header.
648 18         37 push($self->{HEADINGS}->@*, $text);
649 18         36 my $tag = 'S' . scalar($self->{HEADINGS}->@*);
650 18         45 return $self->_heading($text, 2, "#$tag");
651             }
652              
653             # All the other headings, which just hand off to the heading method.
654 2     2   5 sub _cmd_head2 { my ($self, $j, $text) = @_; return $self->_heading($text, 3) }
  2         6  
655 1     1   3 sub _cmd_head3 { my ($self, $j, $text) = @_; return $self->_heading($text, 4) }
  1         5  
656 1     1   3 sub _cmd_head4 { my ($self, $j, $text) = @_; return $self->_heading($text, 5) }
  1         4  
657              
658             ##############################################################################
659             # List handling
660             ##############################################################################
661              
662             # Called for each paragraph of text that we see inside an item. It's also
663             # called with no text when it's time to start an item even though there wasn't
664             # any text associated with it (which happens for description lists). The top
665             # of the ITEMS stack will hold the command that should be used to open the
666             # item block in thread.
667             #
668             # $text - Contents of the text block inside =item
669             sub _item {
670 19     19   31 my ($self, $text) = @_;
671              
672             # If there wasn't anything waiting, we're in the second or subsequent
673             # paragraph of the item text. Just output it.
674 19 100       41 if (!$self->{ITEM_PENDING}) {
675 5         12 $self->_output($text);
676 5         7 return;
677             }
678              
679             # We're starting a new item. Close any pending =item block.
680 14 100       26 if ($self->{ITEM_OPEN}) {
681 3         8 $self->_output("]\n");
682 3         4 $self->{ITEM_OPEN} = 0;
683             }
684              
685             # Now, output the start of the item tag plus the text, if any.
686 14         25 my $tag = $self->{ITEMS}[-1];
687 14   100     60 $self->_output($tag . "\n[" . ($text // q{}));
688 14         20 $self->{ITEM_OPEN} = 1;
689 14         22 $self->{ITEM_PENDING} = 0;
690 14         19 return;
691             }
692              
693             # Output any waiting items and close any pending blocks.
694             sub _finish_item {
695 33     33   57 my ($self) = @_;
696 33 100       79 if ($self->{ITEM_PENDING}) {
697 1         3 $self->_item();
698             }
699 33 100       63 if ($self->{ITEM_OPEN}) {
700 11         24 $self->_output("]\n");
701 11         18 $self->{ITEM_OPEN} = 0;
702             }
703 33         44 return;
704             }
705              
706             # Handle the beginning of an =over block. This is called by the handlers for
707             # the four different types of lists (bullet, number, desc, and block). Update
708             # our internal tracking for =over blocks.
709             sub _over_start {
710 11     11   19 my ($self) = @_;
711              
712             # If an item was already pending, we have nested =over blocks. Open the
713             # outer block here before we start processing items for the inside block.
714 11 100       26 if ($self->{ITEM_PENDING}) {
715 2         6 $self->_item();
716             }
717              
718             # Start a new block.
719 11         15 $self->{ITEM_OPEN} = 0;
720 11         23 push($self->{ITEMS}->@*, q{});
721 11         17 return;
722             }
723              
724             # Handle the end of a list. Output any waiting items, close any pending
725             # blocks, and pop one level of item off the item stack.
726             sub _over_end {
727 11     11   19 my ($self) = @_;
728              
729             # If there is a waiting item or a pending close bracket, output it now.
730 11         25 $self->_finish_item();
731              
732             # Pop the item off the stack.
733 11         19 pop($self->{ITEMS}->@*);
734              
735             # Set pending based on whether there's still another level of item open.
736 11 100       27 if ($self->{ITEMS}->@* > 0) {
737 4         5 $self->{ITEM_OPEN} = 1;
738             }
739 11         48 return;
740             }
741              
742             # All the individual start commands for the specific types of lists. These
743             # are all dispatched to the relevant common routine except for block.
744             # Pod::Simple gives us the type information on both the =over and the =item.
745             # We ignore it here and use it when we see the =item.
746 3     3   7 sub _start_over_bullet { my ($self) = @_; return $self->_over_start() }
  3         8  
747 1     1   3 sub _start_over_number { my ($self) = @_; return $self->_over_start() }
  1         3  
748 5     5   11 sub _start_over_text { my ($self) = @_; return $self->_over_start() }
  5         10  
749              
750             # Over of type block (which is =over without any =item) has to be handled
751             # specially, since normally we defer issuing the tag until we see the first
752             # =item and that won't happen here.
753             sub _start_over_block {
754 2     2   5 my ($self) = @_;
755 2         10 $self->_over_start();
756 2         4 $self->{ITEMS}[-1] = '\\block';
757 2         4 $self->{ITEM_PENDING} = 1;
758 2         6 $self->_item();
759 2         2 return;
760             }
761              
762             # Likewise for the end commands.
763 2     2   4 sub _end_over_block { my ($self) = @_; return $self->_over_end() }
  2         6  
764 3     3   5 sub _end_over_bullet { my ($self) = @_; return $self->_over_end() }
  3         7  
765 1     1   3 sub _end_over_number { my ($self) = @_; return $self->_over_end() }
  1         3  
766 5     5   11 sub _end_over_text { my ($self) = @_; return $self->_over_end() }
  5         10  
767              
768             # An individual list item command. Note that this fires when the =item
769             # command is seen, not when we've accumulated all the text that's part of that
770             # item. We may have some body text and we may not, but we have to defer the
771             # end of the item until the surrounding =over is closed.
772             #
773             # $type - The type of the item
774             # $attrs - Attributes for this command
775             # $text - The text of the block
776             sub _item_common {
777 12     12   25 my ($self, $type, $attrs, $text) = @_;
778              
779             # If we saw an =item command, any previous item block is finished, so
780             # output that now.
781 12 50       27 if ($self->{ITEM_PENDING}) {
782 0         0 $self->_item();
783             }
784              
785             # The top of the stack should now contain our new type of item.
786 12         24 $self->{ITEMS}[-1] = "\\$type";
787              
788             # We now have an item waiting for output.
789 12         18 $self->{ITEM_PENDING} = 1;
790              
791             # If the type is desc, anything in $text is the description title and
792             # needs to be appended to our ITEM.
793 12 100       23 if ($self->{ITEMS}[-1] eq '\\desc') {
794 8         17 $text =~ s{ \s+ \z }{}xms;
795 8         17 $self->{ITEMS}[-1] .= "[$text]";
796             }
797              
798             # Otherwise, anything in $text is body text. Handle that now.
799             else {
800 4         9 $self->_item($self->_reformat($text));
801             }
802              
803 12         25 return;
804             }
805              
806             # All the various item commands just call item_common.
807             ## no critic (Subroutines::RequireArgUnpacking)
808 3     3   6 sub _cmd_item_bullet { my $s = shift; return $s->_item_common('bullet', @_) }
  3         8  
809 1     1   2 sub _cmd_item_number { my $s = shift; return $s->_item_common('number', @_) }
  1         3  
810 8     8   10 sub _cmd_item_text { my $s = shift; return $s->_item_common('desc', @_) }
  8         20  
811             ## use critic
812             ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
813              
814             ##############################################################################
815             # Formatting codes
816             ##############################################################################
817              
818             # The simple ones. These are here mostly so that subclasses can override them
819             # and do more complicated things.
820             #
821             # $attrs - Attributes for this command
822             # $text - The text of the block
823             #
824             # Returns: The formatted text
825 2     2   5 sub _cmd_b { my ($self, $attrs, $text) = @_; return "\\bold[$text]" }
  2         6  
826 2     2   5 sub _cmd_c { my ($self, $attrs, $text) = @_; return "\\code[$text]" }
  2         5  
827 2     2   5 sub _cmd_f { my ($self, $attrs, $text) = @_; return "\\italic(file)[$text]" }
  2         7  
828 2     2   6 sub _cmd_i { my ($self, $attrs, $text) = @_; return "\\italic[$text]" }
  2         5  
829 1     1   3 sub _cmd_x { return q{} }
830              
831             # Format a link. Don't try to generate hyperlinks for anything other than
832             # normal URLs and section links within our same document. For the latter, we
833             # can only do that for sections we've already seen; for everything else, use a
834             # PLACEHOLDER tag that we'll try to replace with a real link as the last step
835             # of formatting the document.
836             #
837             # $attrs - Attributes for this command
838             # $text - The text of the block
839             #
840             # Returns: The formatted link
841             sub _cmd_l {
842 11     11   23 my ($self, $attrs, $text) = @_;
843 11 100       36 if ($attrs->{type} eq 'url') {
    50          
844 2 100 66     11 if (!defined($attrs->{to}) || $attrs->{to} eq $text) {
845 1         19 return "<\\link[$text][$text]>";
846             } else {
847 1         19 return "\\link[$attrs->{to}][$text]";
848             }
849             } elsif ($attrs->{type} eq 'pod') {
850 9         13 my $page = $attrs->{to};
851 9         12 my $section = $attrs->{section};
852 9 100 66     34 if (!defined($page) && defined($section)) {
853 7         11 my $tag = 'PLACEHOLDER';
854 7         372 for my $i (0 .. scalar($self->{HEADINGS}->$#*)) {
855 10 100       80 if ($self->{HEADINGS}[$i] eq $section) {
856 2         30 $tag = 'S' . ($i + 1);
857 2         4 last;
858             }
859             }
860 7         98 $text =~ s{ \A \" }{}xms;
861 7         25 $text =~ s{ \" \z }{}xms;
862 7         24 return "\\link[#$tag][$text]";
863             }
864             }
865              
866             # Fallthrough just returns the preformatted text from Pod::Simple.
867 2   50     7 return $text // q{};
868             }
869              
870             ##############################################################################
871             # Module return value and documentation
872             ##############################################################################
873              
874             1;
875             __END__