File Coverage

blib/lib/Pod/Thread.pm
Criterion Covered Total %
statement 259 330 78.4
branch 63 100 63.0
condition 10 34 29.4
subroutine 34 53 64.1
pod 1 38 2.6
total 367 555 66.1


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