File Coverage

blib/lib/Pod/Thread.pm
Criterion Covered Total %
statement 340 345 98.5
branch 87 100 87.0
condition 23 32 71.8
subroutine 55 55 100.0
pod 1 1 100.0
total 506 533 94.9


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.01;
14              
15 2     2   112458 use 5.024;
  2         16  
16 2     2   1591 use autodie;
  2         27041  
  2         10  
17 2     2   11957 use warnings;
  2         4  
  2         85  
18              
19 2     2   12 use base qw(Pod::Simple);
  2         3  
  2         1370  
20              
21 2     2   61772 use Carp qw(croak);
  2         5  
  2         143  
22 2     2   631 use Encode qw(encode);
  2         10815  
  2         105  
23 2     2   2776 use Text::Balanced qw(extract_bracketed);
  2         35219  
  2         161  
24 2     2   1012 use Text::Wrap qw(wrap);
  2         5221  
  2         10140  
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 20     20 1 31864 my ($class, %opts) = @_;
61 20         83 my $self = $class->SUPER::new;
62              
63             # Tell Pod::Simple to handle S<> by automatically inserting E.
64 20         437 $self->nbsp_for_S(1);
65              
66             # The =for and =begin targets that we accept.
67 20         170 $self->accept_targets('thread');
68              
69             # Ensure that contiguous blocks of code are merged together.
70 20         310 $self->merge_text(1);
71              
72             # Preserve whitespace whenever possible to make debugging easier.
73 20         126 $self->preserve_whitespace(1);
74              
75             # Always send errors to standard error.
76 20         116 $self->no_errata_section(1);
77 20         119 $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 20         123 my @opts = map { ("opt_$_", $opts{$_}) } keys %opts;
  32         131  
84 20         34 %{$self} = (%{$self}, @opts);
  20         95  
  20         62  
85              
86 20         71 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 104     104   889 my ($self, $text) = @_;
113 104 100       238 if (!$self->{LITERAL}) {
114 100         193 $text =~ s{ \\ }{\\\\}xmsg;
115 100         194 $text =~ s{ ([\[\]]) }{'\\entity[' . ord($1) . ']'}xmseg;
  8         32  
116             }
117 104         160 my $tag = $self->{PENDING}[-1];
118 104         196 $tag->[1] .= $text;
119 104         206 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 264     264   398 my ($self, $element) = @_;
130 264         431 $element =~ tr{-}{_};
131 264         347 $element =~ tr{A-Z}{a-z};
132 264         358 $element =~ tr{_a-z0-9}{}cd;
133 264         512 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 132     132   49659 my ($self, $element, $attrs) = @_;
145 132         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 132 100       647 if ($self->can("_cmd_$method")) {
    50          
150 99         253 push($self->{PENDING}->@*, [$attrs, q{}]);
151             } elsif ($self->can("_start_$method")) {
152 33         74 $method = '_start_' . $method;
153 33         87 $self->$method($attrs, q{});
154             }
155 132         282 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 132     132   2336 my ($self, $element) = @_;
165 132         227 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 132 100       471 if ($self->can("_cmd_$method")) {
    50          
171 99         189 my $tag_ref = pop($self->{PENDING}->@*);
172 99         184 $method = '_cmd_' . $method;
173 99         233 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 99 100       222 if (defined($text)) {
179 20 50       43 if ($self->{PENDING}->@* > 1) {
180 20         41 $self->{PENDING}[-1][1] .= $text;
181             } else {
182 0         0 $self->_output($text);
183             }
184             }
185 99         234 return;
186             } elsif ($self->can("_end_$method")) {
187 33         66 $method = '_end_' . $method;
188 33         75 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 33     33   54 my ($self, $text) = @_;
205 33         242 $text =~ s{ \s* \z }{\n\n}xms;
206 33         87 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 101     101   173 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 101 100       188 if ($self->{SPACE}) {
222 62 100       187 if ($text =~ s{ \A \] \s* \n }{}xms) {
223 11         20 $self->{OUTPUT} .= "]\n";
224             }
225 62         97 $self->{OUTPUT} .= $self->{SPACE};
226 62         102 undef $self->{SPACE};
227             }
228              
229             # Defer any trailing newlines beyond a single newline.
230 101 100       358 if ($text =~ s{ \n (\n+) \z }{\n}xms) {
231 62         186 $self->{SPACE} = $1;
232             }
233              
234             # Append the text to the output.
235 101         207 $self->{OUTPUT} .= $text;
236 101         145 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 20     20   28 my ($self) = @_;
244 20         37 my $output = $self->{OUTPUT};
245              
246             # Encode if necessary and then output.
247 20 50       45 if ($self->{ENCODE}) {
248 20         37 $output = encode('UTF-8', $output);
249             }
250 20 50       792 print { $self->{output_fh} } $output
  20         46  
251             or die "Cannot write to output: $!\n";
252              
253             # Clear the output to avoid sending it twice.
254 20         167 $self->{OUTPUT} = q{};
255 20         31 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   8 my ($self) = @_;
268 5 100       12 return q{} if !$self->{HEADINGS}->@*;
269              
270             # Construct and return the table of contents.
271 4         7 my $output = "\\h2[Table of Contents]\n\n";
272 4         9 for my $i (0 .. $self->{HEADINGS}->$#*) {
273 9         13 my $tag = 'S' . ($i + 1);
274 9         17 my $section = $self->{HEADINGS}[$i];
275 9         24 $output .= "\\number(packed)[\\link[#$tag][$section]]\n";
276             }
277 4         9 $output .= "\n";
278 4         9 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   20 my ($self, $heading) = @_;
289 11         62 my @words = split(m{ (\s+) }xms, $heading);
290 11         23 for my $word (@words) {
291 63 100 100     184 if ($word !~ m{ _ }xms && $word !~ m{ \A \\ }xms) {
292 57         78 $word = lc($word);
293 57 100       91 if ($word ne 'and') {
294 55         91 $word = ucfirst($word);
295             }
296             }
297             }
298 11         37 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 6     6   13 my ($self) = @_;
309 6 100       15 return q{} if !$self->{HEADINGS}->@*;
310              
311             # Build the start of the navbar.
312 5         6 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         9 my $pending = q{};
319 5         7 my $length = 0;
320 5         14 for my $i (0 .. scalar($self->{HEADINGS}->$#*)) {
321 11         19 my $tag = 'S' . ($i + 1);
322 11         17 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     33 if ($length > 0 && $length + length($section) > $NAVBAR_LENGTH) {
327 1         4 $output .= "$pending\\break\n ";
328 1         3 $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         9 $length += length(q{ | });
336             }
337              
338             # Convert the section names to titlecase.
339 11         18 my $name = $self->_capitalize_for_navbar($section);
340              
341             # Add it to the current line.
342 11         26 $pending .= "\\link[#$tag][$name]\n";
343 11         23 $length += length($name);
344             }
345              
346             # Collect any remaining partial line and the end of the navbar.
347 5 50       13 if (length($pending) > 0) {
348 5         11 $output .= $pending;
349             }
350 5         8 $output .= "]\n\n";
351 5         12 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 20     20   34 my ($self) = @_;
363 20   50     78 my $style = $self->{opt_style} || q{};
364 20         27 my $output = q{};
365              
366             # Add the basic title, page heading, and style if we saw a title.
367 20 100       43 if ($self->{TITLE}) {
368 5         16 $output .= "\\heading[$self->{TITLE}][$style]\n\n";
369 5         13 $output .= "\\h1[$self->{TITLE}]\n\n";
370             } else {
371 15         29 $output .= "\\heading[][]\n\n";
372             }
373              
374             # If there is a subheading, add it.
375 20 100       46 if (defined($self->{SUBHEADING})) {
376 4         10 $output .= "\\class(subhead)[($self->{SUBHEADING})]\n\n";
377             }
378              
379             # If a navbar or table of contents was requested, add it.
380 20 100       35 if ($self->{opt_navbar}) {
381 6         12 $output .= $self->_navbar();
382             }
383 20 100       47 if ($self->{opt_contents}) {
384 5         11 $output .= $self->_contents();
385             }
386              
387             # Return the results.
388 20         38 return $output;
389             }
390              
391             # Handle the beginning of a POD file. We only output something if title is
392             # set, in which case we output the title and other header information at the
393             # beginning of the resulting output file.
394             #
395             # $attrs - Attributes of the start document tag
396             sub _start_document {
397 20     20   38 my ($self, $attrs) = @_;
398              
399             # If the document has no content, set the appropriate internal flag.
400 20 100       38 if ($attrs->{contentless}) {
401 1         2 $self->{CONTENTLESS} = 1;
402             } else {
403 19         31 delete $self->{CONTENTLESS};
404             }
405              
406             # Initialize per-document variables.
407             #<<<
408 20         37 $self->{HEADINGS} = [];
409 20         35 $self->{IN_NAME} = 0;
410 20         31 $self->{ITEM_OPEN} = 0;
411 20         29 $self->{ITEM_PENDING} = 0;
412 20         39 $self->{ITEMS} = [];
413 20         25 $self->{LITERAL} = 0;
414 20         38 $self->{OUTPUT} = q{};
415 20         40 $self->{PENDING} = [[]];
416 20         35 $self->{SUBHEADING} = undef;
417 20   100     109 $self->{TITLE} = $self->{opt_title} // q{};
418             #>>>
419              
420             # Check whether our output file handle already has a PerlIO encoding layer
421             # set. If it does not, we'll need to encode our output before printing
422             # it. Wrap the check in an eval to handle versions of Perl without
423             # PerlIO.
424 20         44 $self->{ENCODE} = 1;
425 20         27 eval {
426 20         48 my @options = (output => 1, details => 1);
427 20         82 my @layers = PerlIO::get_layers($self->{output_fh}->**, @options);
428 20 50 33     67 if ($layers[-1] && ($layers[-1] & PerlIO::F_UTF8())) {
429 0         0 $self->{ENCODE} = 0;
430             }
431             };
432 20         36 return;
433             }
434              
435             # Canonicalize a heading for internal links. We run both the anchor text and
436             # the heading itself through this function so that whitespace differences
437             # don't cause us to fail to create the link.
438             #
439             # Note that this affects only the end-of-document rewriting, not the links we
440             # create as we go, because this case is rare and doing it as we go would
441             # require more state tracking.
442             #
443             # $heading - Text of heading
444             #
445             # Returns: Canonicalized heading text
446             sub _canonicalize_heading {
447 23     23   38 my ($self, $heading) = @_;
448 23         88 $heading =~ s{ \s+ }{ }xmsg;
449 23         93 return $heading;
450             }
451              
452             # Handle the end of the document. Tack \signature onto the end, output the
453             # header and the accumulated output, and die if we saw any errors.
454             #
455             # Throws: Text exception if there were any errata
456             sub _end_document {
457 20     20   34 my ($self) = @_;
458              
459             # Output the \signature command if we saw any content.
460 20 100       54 if (!$self->{CONTENTLESS}) {
461 19         43 $self->_output("\\signature\n");
462             }
463              
464             # Search for any unresolved links and try to fix their anchors. If we
465             # never saw the heading in question, remove the \link command. We have to
466             # use Text::Balanced and substr surgery to extract the anchor text since
467             # it may contain arbitrary markup.
468             #
469             # This is very inefficient for large documents, but I doubt anything
470             # processed by this module will be large enough to matter.
471 20         32 my $i = 1;
472 20         25 my $search = '\\link[#PLACEHOLDER]';
473 20         25 my $start = 0;
474 18         35 my %headings = map { ('[' . $self->_canonicalize_heading($_) . ']', $i++) }
475 20         44 $self->{HEADINGS}->@*;
476 20         77 while (($start = index($self->{OUTPUT}, $search, $start)) != -1) {
477 5         16 my $text = substr($self->{OUTPUT}, $start + length($search));
478 5         17 my ($anchor) = extract_bracketed($text, '[]', undef);
479 5         992 my $heading;
480 5 50       11 if ($anchor) {
481 5         13 $heading = $self->_canonicalize_heading($anchor);
482             }
483              
484             # If this is a known heading, replace #PLACEHOLDER with the link to
485             # that heading and continue processing with the anchor text.
486             # Otherwise, replace the entire \link command with the anchor text and
487             # continue processing after it.
488 5 100 66     34 if (defined($anchor) && defined($headings{$heading})) {
489 4         9 $start += length('\\link[');
490 4         10 my $link = "#S$headings{$heading}";
491 4         22 substr($self->{OUTPUT}, $start, length('#PLACEHOLDER'), $link);
492             } else {
493 1         3 my $length = length('\\link[#PLACEHOLDER]') + length($anchor);
494 1         2 $anchor = substr($anchor, 1, -1);
495 1         3 substr($self->{OUTPUT}, $start, $length, $anchor);
496 1         4 $start += length($anchor);
497             }
498             }
499              
500             # Output the header.
501 20         48 my $header = $self->_header();
502 20 50       44 if ($self->{ENCODE}) {
503 20         66 $header = encode('UTF-8', $header);
504             }
505 20 50       1277 print { $self->{output_fh} } $header
  20         79  
506             or die "Cannot write to output: $!\n";
507              
508             # Flush the rest of the output.
509 20         213 $self->_flush_output();
510              
511             # Die if we saw any errors.
512 20 100       56 if ($self->any_errata_seen()) {
513 1         238 croak('POD document had syntax errors');
514             }
515 19         108 return;
516             }
517              
518             ##############################################################################
519             # Text blocks
520             ##############################################################################
521              
522             # Called for a regular text block. There are two tricky parts here. One is
523             # that if there is a pending item tag, we need to format this as an item
524             # paragraph. The second is that if we're in the NAME section and see the name
525             # and description of the page, we should print out the header.
526             #
527             # $attrs - Attributes for this command
528             # $text - The text of the block
529             sub _cmd_para {
530 33     33   60 my ($self, $attrs, $text) = @_;
531              
532             # Ensure the text block ends with a single newline.
533 33         120 $text =~ s{ \s+ \z }{\n}xms;
534              
535             # If we're inside an item block, handle this as an item.
536 33 100 66     48 if (@{ $self->{ITEMS} } > 0) {
  33 100       166  
537 8         16 $self->_item($self->_reformat($text));
538             }
539              
540             # If we're in the NAME section and see a line that looks like the special
541             # NAME section of a man page, stash that information for the page heading.
542             elsif ($self->{IN_NAME} && $text =~ $NAME_REGEX) {
543 4         17 my ($name, $description) = ($1, $2);
544 4         10 $self->{TITLE} = $name;
545 4         7 $self->{SUBHEADING} = $description;
546             }
547              
548             # Otherwise, this is a regular text block, so just output it with a
549             # trailing blank line.
550             else {
551 21         58 $self->_output($self->_reformat($text . "\n"));
552             }
553 33         63 return;
554             }
555              
556             # Called for a verbatim paragraph. The only trick is knowing whether to use
557             # the item method to handle it or just print it out directly.
558             #
559             # $attrs - Attributes for this command
560             # $text - The text of the block
561             sub _cmd_verbatim {
562 4     4   9 my ($self, $attrs, $text) = @_;
563              
564             # Ignore empty verbatim paragraphs.
565 4 50       17 if ($text =~ m{ \A \s* \z }xms) {
566 0         0 return;
567             }
568              
569             # Ensure the paragraph ends in a bracket and two newlines.
570 4         29 $text =~ s{ \s* \z }{\]\n\n}xms;
571              
572             # Pass the text to either item or output.
573 4 100       7 if (@{ $self->{ITEMS} } > 0) {
  4         11  
574 2         8 $self->_item("\\pre\n[$text");
575             } else {
576 2         7 $self->_output("\\pre\n[$text");
577             }
578 4         7 return;
579             }
580              
581             # Called for literal text produced by =for and similar constructs. Just
582             # output the text verbatim with cleaned-up whitespace.
583             #
584             # $attrs - Attributes for this command
585             # $text - The text of the block
586             sub _cmd_data {
587 4     4   10 my ($self, $attrs, $text) = @_;
588 4         14 $text =~ s{ \A (\s*\n)+ }{}xms;
589 4         22 $text =~ s{ \s* \z }{\n\n}xms;
590 4         13 $self->_output($text);
591 4         5 return;
592             }
593              
594             # Called when =for and similar constructs are started or ended. Set or clear
595             # the literal flag so that we won't escape the text on the way in.
596             #<<<
597 2     2   6 sub _start_for { my ($self) = @_; $self->{LITERAL} = 1; return; }
  2         4  
  2         4  
598 2     2   5 sub _end_for { my ($self) = @_; $self->{LITERAL} = 0; return; }
  2         4  
  2         4  
599             #>>>
600              
601             ##############################################################################
602             # Headings
603             ##############################################################################
604              
605             # The common code for handling all headings. Take care of any pending items
606             # or lists and then output the thread code for the heading.
607             #
608             # $text - The text of the heading itself
609             # $level - The level of the heading as a number (2..5)
610             # $tag - An optional tag for the heading
611             sub _heading {
612 22     22   46 my ($self, $text, $level, $tag) = @_;
613              
614             # If there is a waiting item or a pending close bracket, output it now.
615 22         69 $self->_finish_item();
616              
617             # Strip any trailing whitespace.
618 22         48 $text =~ s{ \s+ \z }{}xms;
619              
620             # Output the heading thread.
621 22 100       41 if (defined $tag) {
622 18         58 $self->_output("\\h$level($tag)[$text]\n\n");
623             } else {
624 4         15 $self->_output("\\h$level" . "[$text]\n\n");
625             }
626 22         45 return;
627             }
628              
629             # First level heading. This requires some special handling to update the
630             # IN_NAME setting based on whether we're currently in the NAME section. Also
631             # add a tag to the heading if we have section information.
632             #
633             # $attrs - Attributes for this command
634             # $text - The text of the block
635             #
636             # Returns: The result of the heading method
637             sub _cmd_head1 {
638 22     22   39 my ($self, $attrs, $text) = @_;
639              
640             # Strip whitespace from the text since we're going to compare it to other
641             # things.
642 22         63 $text =~ s{ \s+ \z }{}xms;
643              
644             # If we're in the NAME section and no title was explicitly set, set the
645             # flag used in cmd_para to parse the NAME text specially and then do
646             # nothing else (since we won't print out the NAME section as itself.
647 22 100 66     72 if ($text eq 'NAME' && !defined($self->{opt_title})) {
648 4         7 $self->{IN_NAME} = 1;
649 4         8 return;
650             }
651 18         31 $self->{IN_NAME} = 0;
652              
653             # Not in the name section. Record the heading and a tag to the header.
654 18         34 push($self->{HEADINGS}->@*, $text);
655 18         37 my $tag = 'S' . scalar($self->{HEADINGS}->@*);
656 18         43 return $self->_heading($text, 2, "#$tag");
657             }
658              
659             # All the other headings, which just hand off to the heading method.
660 2     2   6 sub _cmd_head2 { my ($self, $j, $text) = @_; return $self->_heading($text, 3) }
  2         5  
661 1     1   4 sub _cmd_head3 { my ($self, $j, $text) = @_; return $self->_heading($text, 4) }
  1         3  
662 1     1   4 sub _cmd_head4 { my ($self, $j, $text) = @_; return $self->_heading($text, 5) }
  1         3  
663              
664             ##############################################################################
665             # List handling
666             ##############################################################################
667              
668             # Called for each paragraph of text that we see inside an item. It's also
669             # called with no text when it's time to start an item even though there wasn't
670             # any text associated with it (which happens for description lists). The top
671             # of the ITEMS stack will hold the command that should be used to open the
672             # item block in thread.
673             #
674             # $text - Contents of the text block inside =item
675             sub _item {
676 19     19   35 my ($self, $text) = @_;
677              
678             # If there wasn't anything waiting, we're in the second or subsequent
679             # paragraph of the item text. Just output it.
680 19 100       40 if (!$self->{ITEM_PENDING}) {
681 5         13 $self->_output($text);
682 5         6 return;
683             }
684              
685             # We're starting a new item. Close any pending =item block.
686 14 100       29 if ($self->{ITEM_OPEN}) {
687 3         8 $self->_output("]\n");
688 3         6 $self->{ITEM_OPEN} = 0;
689             }
690              
691             # Now, output the start of the item tag plus the text, if any.
692 14         22 my $tag = $self->{ITEMS}[-1];
693 14   100     61 $self->_output($tag . "\n[" . ($text // q{}));
694 14         24 $self->{ITEM_OPEN} = 1;
695 14         18 $self->{ITEM_PENDING} = 0;
696 14         22 return;
697             }
698              
699             # Output any waiting items and close any pending blocks.
700             sub _finish_item {
701 33     33   48 my ($self) = @_;
702 33 100       71 if ($self->{ITEM_PENDING}) {
703 1         3 $self->_item();
704             }
705 33 100       63 if ($self->{ITEM_OPEN}) {
706 11         24 $self->_output("]\n");
707 11         16 $self->{ITEM_OPEN} = 0;
708             }
709 33         48 return;
710             }
711              
712             # Handle the beginning of an =over block. This is called by the handlers for
713             # the four different types of lists (bullet, number, desc, and block). Update
714             # our internal tracking for =over blocks.
715             sub _over_start {
716 11     11   20 my ($self) = @_;
717              
718             # If an item was already pending, we have nested =over blocks. Open the
719             # outer block here before we start processing items for the inside block.
720 11 100       25 if ($self->{ITEM_PENDING}) {
721 2         5 $self->_item();
722             }
723              
724             # Start a new block.
725 11         13 $self->{ITEM_OPEN} = 0;
726 11         25 push($self->{ITEMS}->@*, q{});
727 11         18 return;
728             }
729              
730             # Handle the end of a list. Output any waiting items, close any pending
731             # blocks, and pop one level of item off the item stack.
732             sub _over_end {
733 11     11   20 my ($self) = @_;
734              
735             # If there is a waiting item or a pending close bracket, output it now.
736 11         22 $self->_finish_item();
737              
738             # Pop the item off the stack.
739 11         17 pop($self->{ITEMS}->@*);
740              
741             # Set pending based on whether there's still another level of item open.
742 11 100       27 if ($self->{ITEMS}->@* > 0) {
743 4         6 $self->{ITEM_OPEN} = 1;
744             }
745 11         47 return;
746             }
747              
748             # All the individual start commands for the specific types of lists. These
749             # are all dispatched to the relevant common routine except for block.
750             # Pod::Simple gives us the type information on both the =over and the =item.
751             # We ignore it here and use it when we see the =item.
752             #<<<
753 3     3   7 sub _start_over_bullet { my ($self) = @_; return $self->_over_start() }
  3         8  
754 1     1   3 sub _start_over_number { my ($self) = @_; return $self->_over_start() }
  1         3  
755 5     5   13 sub _start_over_text { my ($self) = @_; return $self->_over_start() }
  5         10  
756             #>>>
757              
758             # Over of type block (which is =over without any =item) has to be handled
759             # specially, since normally we defer issuing the tag until we see the first
760             # =item and that won't happen here.
761             sub _start_over_block {
762 2     2   5 my ($self) = @_;
763 2         10 $self->_over_start();
764 2         5 $self->{ITEMS}[-1] = '\\block';
765 2         4 $self->{ITEM_PENDING} = 1;
766 2         5 $self->_item();
767 2         2 return;
768             }
769              
770             # Likewise for the end commands.
771             #<<<
772 2     2   4 sub _end_over_block { my ($self) = @_; return $self->_over_end() }
  2         5  
773 3     3   7 sub _end_over_bullet { my ($self) = @_; return $self->_over_end() }
  3         6  
774 1     1   4 sub _end_over_number { my ($self) = @_; return $self->_over_end() }
  1         3  
775 5     5   10 sub _end_over_text { my ($self) = @_; return $self->_over_end() }
  5         10  
776             #>>>
777              
778             # An individual list item command. Note that this fires when the =item
779             # command is seen, not when we've accumulated all the text that's part of that
780             # item. We may have some body text and we may not, but we have to defer the
781             # end of the item until the surrounding =over is closed.
782             #
783             # $type - The type of the item
784             # $attrs - Attributes for this command
785             # $text - The text of the block
786             sub _item_common {
787 12     12   24 my ($self, $type, $attrs, $text) = @_;
788              
789             # If we saw an =item command, any previous item block is finished, so
790             # output that now.
791 12 50       29 if ($self->{ITEM_PENDING}) {
792 0         0 $self->_item();
793             }
794              
795             # The top of the stack should now contain our new type of item.
796 12         35 $self->{ITEMS}[-1] = "\\$type";
797              
798             # We now have an item waiting for output.
799 12         22 $self->{ITEM_PENDING} = 1;
800              
801             # If the type is desc, anything in $text is the description title and
802             # needs to be appended to our ITEM.
803 12 100       27 if ($self->{ITEMS}[-1] eq '\\desc') {
804 8         17 $text =~ s{ \s+ \z }{}xms;
805 8         24 $self->{ITEMS}[-1] .= "[$text]";
806             }
807              
808             # Otherwise, anything in $text is body text. Handle that now.
809             else {
810 4         8 $self->_item($self->_reformat($text));
811             }
812              
813 12         26 return;
814             }
815              
816             # All the various item commands just call item_common.
817             ## no critic (Subroutines::RequireArgUnpacking)
818             #<<<
819 3     3   5 sub _cmd_item_bullet { my $s = shift; return $s->_item_common('bullet', @_) }
  3         8  
820 1     1   3 sub _cmd_item_number { my $s = shift; return $s->_item_common('number', @_) }
  1         4  
821 8     8   10 sub _cmd_item_text { my $s = shift; return $s->_item_common('desc', @_) }
  8         17  
822             #>>>
823             ## use critic
824             ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
825              
826             ##############################################################################
827             # Formatting codes
828             ##############################################################################
829              
830             # The simple ones. These are here mostly so that subclasses can override them
831             # and do more complicated things.
832             #
833             # $attrs - Attributes for this command
834             # $text - The text of the block
835             #
836             # Returns: The formatted text
837 2     2   5 sub _cmd_b { my ($self, $attrs, $text) = @_; return "\\bold[$text]" }
  2         5  
838 2     2   5 sub _cmd_c { my ($self, $attrs, $text) = @_; return "\\code[$text]" }
  2         5  
839 2     2   6 sub _cmd_f { my ($self, $attrs, $text) = @_; return "\\italic(file)[$text]" }
  2         6  
840 2     2   5 sub _cmd_i { my ($self, $attrs, $text) = @_; return "\\italic[$text]" }
  2         16  
841 1     1   2 sub _cmd_x { return q{} }
842              
843             # Format a link. Don't try to generate hyperlinks for anything other than
844             # normal URLs and section links within our same document. For the latter, we
845             # can only do that for sections we've already seen; for everything else, use a
846             # PLACEHOLDER tag that we'll try to replace with a real link as the last step
847             # of formatting the document.
848             #
849             # $attrs - Attributes for this command
850             # $text - The text of the block
851             #
852             # Returns: The formatted link
853             sub _cmd_l {
854 11     11   22 my ($self, $attrs, $text) = @_;
855 11 100       64 if ($attrs->{type} eq 'url') {
    50          
856 2 100 66     11 if (!defined($attrs->{to}) || $attrs->{to} eq $text) {
857 1         19 return "<\\link[$text][$text]>";
858             } else {
859 1         19 return "\\link[$attrs->{to}][$text]";
860             }
861             } elsif ($attrs->{type} eq 'pod') {
862 9         17 my $page = $attrs->{to};
863 9         14 my $section = $attrs->{section};
864 9 100 66     43 if (!defined($page) && defined($section)) {
865 7         11 my $tag = 'PLACEHOLDER';
866 7         20 for my $i (0 .. scalar($self->{HEADINGS}->$#*)) {
867 10 100       74 if ($self->{HEADINGS}[$i] eq $section) {
868 2         31 $tag = 'S' . ($i + 1);
869 2         4 last;
870             }
871             }
872 7         80 $text =~ s{ \A \" }{}xms;
873 7         23 $text =~ s{ \" \z }{}xms;
874 7         23 return "\\link[#$tag][$text]";
875             }
876             }
877              
878             # Fallthrough just returns the preformatted text from Pod::Simple.
879 2   50     8 return $text // q{};
880             }
881              
882             ##############################################################################
883             # Module return value and documentation
884             ##############################################################################
885              
886             1;
887             __END__