File Coverage

blib/lib/Pod/Peapod.pm
Criterion Covered Total %
statement 19 272 6.9
branch 0 94 0.0
condition 0 12 0.0
subroutine 7 35 20.0
pod 1 16 6.2
total 27 429 6.2


line stmt bran cond sub pod time code
1             package Pod::Peapod;
2              
3 1     1   39077 use 5.008;
  1         5  
  1         44  
4 1     1   6 use strict;
  1         2  
  1         51  
5 1     1   5 use warnings;
  1         7  
  1         32  
6 1     1   18 use Carp;
  1         2  
  1         161  
7              
8             our $VERSION = '0.42';
9              
10 1     1   1617 use Data::Dumper;
  1         12427  
  1         86  
11              
12 1     1   971 use Pod::Simple::Methody;
  1         35765  
  1         52  
13              
14             our @ISA;
15 1     1   4876 BEGIN { push(@ISA,'Pod::Simple'); }
16              
17             #######################################################################
18              
19             my %start_new_line_for_element =
20             (
21             head => 1,
22             for => 1,
23             Document => 1,
24             Para => 1,
25             Verbatim => 1,
26              
27             'over_bullet' => 0,
28             'item_bullet' => 1,
29              
30             'over_text' => 0,
31             'item_text' => 1,
32              
33             'I' => 0, # italics
34             'B' => 0, # bold
35             'C' => 0, # code
36              
37             'L' => 0, # hyperlink
38             );
39              
40             #######################################################################
41             sub New
42             #######################################################################
43             {
44 0     0 0   my ($class) = @_;
45 0           my $parser = $class->SUPER::new();
46 0           $parser->{_show_section_numbers}=1;
47              
48 0           $parser->{_current_attributes}=[ {} ];
49 0           $parser->SetAttribute('_left_margin',0);
50 0           return $parser;
51             }
52              
53             #######################################################################
54             sub parse_string_document
55             #######################################################################
56             {
57 0     0 1   my ($parser, $string)=@_;
58              
59             # call method to clear any preexisting document
60              
61 0           $parser->SUPER::parse_string_document($string);
62              
63             # call method to post process
64             }
65              
66             #######################################################################
67             # the following elements are initialized by this subroutine:
68             # _start_end
69             # _element_type
70             # _head_index (if =head1, =head2, =head3, etc)
71             # any attributes created by Pod::Simple will also be aggregated
72             # into the current attributes. they will NOT be prefixed with an underscore,
73             # so there should be no collisions between Pod::Simple and
74             # Pod::Peapod::Base attributes.
75             #
76             # All other methods will then be called to track their own attributes.
77             #
78             #######################################################################
79             # this method is called by Pod::Simple at the start of every element
80             #######################################################################
81             sub _handle_element_start
82             #######################################################################
83             {
84 0     0     my $parser = shift(@_);
85              
86 0           my $element= shift(@_);
87 0           my $attrs = shift(@_);
88              
89 0           my %attributes = %$attrs;
90              
91 0           $attributes{_start_end}='start';
92              
93              
94             #############################################################
95             # convert _element_type head1 to
96             # _element_type head and a _head_index of 1
97             #############################################################
98 0 0         if($element =~ s{head(\d+)}{head})
99             {
100 0           $attributes{_head_index}=$1;
101             }
102              
103             #############################################################
104             # convert hypens in element type to underscores
105             # this is so element type fits \w+
106             #############################################################
107 0           $element =~ s{\-}{_}g;
108              
109              
110             #############################################################
111             # now store the filtered element type
112             #############################################################
113 0           $attributes{_element_type}=$element;
114              
115             #############################################################
116             # now that we know element type (and stripped head1 to head)
117             # check to see if we should output a newline character.
118             #############################################################
119 0 0         if(exists($start_new_line_for_element{$element}))
120             {
121 0 0         if($start_new_line_for_element{$element})
122             {
123 0           $parser->OutputPodNewLine;
124             }
125             }
126             else
127             {
128 0           die "Error: unknown element type '$element'";
129             }
130              
131 0 0         if($element eq 'head')
132             {
133 0           $parser->OutputTocNewLine;
134             }
135              
136             #############################################################
137             # make sure an array exists to hold current attributes
138             #############################################################
139 0 0         unless(exists($parser->{_current_attributes}))
140 0           { $parser->{_current_attributes} = []; }
141              
142             #############################################################
143             # push basic current attributes onto array.
144             #############################################################
145 0           push(@{$parser->{_current_attributes}}, \%attributes);
  0            
146              
147             #############################################################
148             # with basic current attributes set, call generated attributes
149             #############################################################
150 0           $parser->TrackGeneratedAttributes;
151              
152             #############################################################
153             # handle section number if enabled.
154             #############################################################
155 0 0 0       if(
      0        
156             1
157             and ($element eq 'head')
158             and exists($parser->{_show_section_numbers})
159             and ($parser->{_show_section_numbers})
160             )
161             {
162 0           my $section_number = $parser->GetAttribute('_section_number');
163 0           $parser->SetAttribute('_text_string',$section_number);
164 0           $parser->OutputPodText;
165              
166 0           my $head_index = $parser->GetAttribute('_head_index');
167 0           my $pad = ' 'x($head_index);
168 0           $parser->SetAttribute('_text_string',$pad.$section_number);
169 0           $parser->OutputTocText;
170             }
171              
172             #############################################################
173             # call any specific element handlers that have been declared.
174             #############################################################
175 0           $parser->_specific_element_handler;
176             }
177              
178              
179             #######################################################################
180             # croak gets confused and goes too far back up the call chain sometimes.
181             # 'diecaller' just dies from the point of view of two callers ago.
182             #######################################################################
183             sub diecaller
184             #######################################################################
185             {
186 0     0 0   my $error_string = shift(@_);
187              
188 0           my @caller = caller(1);
189              
190 0           print Dumper \@caller;
191 0           my $module = $caller[1];
192 0           my $line = $caller[2];
193              
194 0           my $string = "$error_string at $module line $line\n";
195 0           die $string;
196              
197             }
198              
199              
200             #######################################################################
201             # use the following methods to search for existence of attribute
202             # anywhere in the array of attribute history.
203             # might have 'head' followed by 'I' (Italic), and will want the
204             # Italicized text to also be part of the 'head' element.
205             #
206             # this method will allow you to see if the 'history'
207             # has an attribute '_element_type' with a value of 'head'
208             #######################################################################
209             sub SearchHistoryForAttributeMatchingValue
210             #######################################################################
211             {
212 0     0 0   my $parser=shift(@_);
213 0           my $attribute=shift(@_);
214 0 0         diecaller("not enough parameters to SearchHistoryForAttributeMatchingValue")if(scalar(@_)==0);
215 0           my $value=shift(@_);
216              
217 0 0         diecaller("Too many parameters to SearchHistoryForAttributeMatchingValue") if(scalar(@_));
218              
219 0           my $match=0;
220 0           my $ref = $parser->{_current_attributes};
221              
222             #eval
223             # {
224 0           foreach my $attrs (@$ref)
225             {
226 0 0 0       if( exists($attrs->{$attribute}) and ($attrs->{$attribute} eq $value) )
227             {
228 0           $match=1 ;
229 0           last;
230             }
231             }
232             # };
233             #diecaller($@) if ($@);
234              
235 0           return $match;
236             }
237              
238              
239              
240             #######################################################################
241             # use the following methods to get a current attribute value
242             #######################################################################
243             sub GetAttribute
244             #######################################################################
245             {
246 0     0 0   my $parser=shift(@_);
247 0           my $attribute=shift(@_);
248              
249 0 0         diecaller("Too many parameters to GetAttribute") if(scalar(@_));
250              
251 0           my $value;
252              
253             eval
254 0           {
255 0           $value = $parser->{_current_attributes}->[-1]->{$attribute};
256             };
257 0 0         diecaller($@) if ($@);
258              
259 0           return $value;
260             }
261              
262             #######################################################################
263             # use the following methods to test for existence of a current attribute
264             #######################################################################
265             sub ExistsAttribute
266             #######################################################################
267             {
268 0     0 0   my $parser=shift(@_);
269 0           my $attribute=shift(@_);
270              
271 0 0         diecaller("Too many parameters to ExistsAttribute") if(scalar(@_));
272              
273 0           my $exists;
274              
275             eval
276 0           {
277 0           $exists = exists($parser->{_current_attributes}->[-1]->{$attribute});
278             };
279 0 0         diecaller($@) if ($@);
280              
281 0           return $exists;
282             }
283              
284             #######################################################################
285             # use the following methods to set a current attribute to a new value
286             #######################################################################
287             sub SetAttribute
288             #######################################################################
289             {
290 0     0 0   my $parser=shift(@_);
291 0           my $attribute=shift(@_);
292              
293 0 0         diecaller("not enough parameters to SetAttribute") if(scalar(@_)==0);
294              
295 0           my $value=shift(@_);
296              
297 0 0         croak "Too many parameters to SetAttribute" if(scalar(@_));
298              
299             eval
300 0           {
301 0           $parser->{_current_attributes}->[-1]->{$attribute}=$value;
302             };
303 0 0         diecaller($@) if ($@);
304              
305 0           return $value;
306             }
307              
308              
309             #######################################################################
310             # use the following methods to get the previous attribute value
311             #######################################################################
312             sub GetPreviousAttribute
313             #######################################################################
314             {
315 0     0 0   my $parser=shift(@_);
316 0           my $attribute=shift(@_);
317              
318 0 0         diecaller("Too many parameters to GetPreviousAttribute") if(scalar(@_));
319              
320 0           my $value;
321              
322             eval
323 0           {
324 0           $value = $parser->{_current_attributes}->[-2]->{$attribute};
325             };
326 0 0         diecaller($@) if ($@);
327              
328 0           return $value;
329             }
330              
331             #######################################################################
332             # use the following methods to test for existence of a current attribute
333             #######################################################################
334             sub ExistsPreviousAttribute
335             #######################################################################
336             {
337 0     0 0   my $parser=shift(@_);
338 0           my $attribute=shift(@_);
339              
340 0 0         diecaller("Too many parameters to ExistsPreviousAttribute")if(scalar(@_));
341              
342 0           my $exists;
343              
344 0 0         return 0 if(scalar(@{$parser->{_current_attributes}}) < 2);
  0            
345              
346             eval
347 0           {
348 0           $exists = exists($parser->{_current_attributes}->[-2]->{$attribute});
349             };
350 0 0         diecaller($@) if ($@);
351              
352 0           return $exists;
353             }
354              
355             #######################################################################
356             # use the following methods to set a current attribute to a new value
357             #######################################################################
358             sub SetPreviousAttribute
359             #######################################################################
360             {
361 0     0 0   my $parser=shift(@_);
362 0           my $attribute=shift(@_);
363              
364 0 0         diecaller("not enough parameters to SetAttribute")if(scalar(@_)==0);
365              
366 0           my $value=shift(@_);
367              
368 0 0         diecaller("Too many parameters to SetPreviousAttribute")if(scalar(@_));
369              
370             eval
371 0           {
372 0           $parser->{_current_attributes}->[-2]->{$attribute}=$value;
373             };
374 0 0         diecaller($@) if ($@);
375              
376 0           return $value;
377             }
378              
379             #######################################################################
380             # this method is called by Pod::Simple at the end of every element
381             #######################################################################
382             sub _handle_element_end
383             #######################################################################
384             {
385 0     0     my $parser = shift(@_);
386              
387 0           $parser->SetAttribute('_start_end', 'end');
388              
389 0           $parser->TrackGeneratedAttributes;
390              
391 0           $parser->_specific_element_handler;
392              
393 0           pop(@{$parser->{_current_attributes}});
  0            
394              
395             }
396              
397              
398             #######################################################################
399             # start_end is either 'start' or 'end'
400             # element type is whatever element type that Pod::Simple uses
401             # this will call a ->start_Para method if it exists.
402             # allows Base classes to add their own behavior easily at specific points.
403             # i.e. want to do something at the start of a Link, just declare a
404             # sub start_L {} method in a base class and it will get called automatically
405             #######################################################################
406             sub _specific_element_handler
407             #######################################################################
408             {
409 0     0     my $parser = shift(@_);
410              
411 0           my $element = $parser->GetAttribute('_element_type');
412 0           my $startend = $parser->GetAttribute('_start_end');
413              
414 0           my $method = $startend .'_'.$element;
415              
416 0 0         if($parser->can($method))
417             {
418 0           $parser->$method;
419             }
420             }
421              
422              
423             #######################################################################
424             sub TrackGeneratedAttributes
425             #######################################################################
426             {
427 0     0 0   my $parser = shift(@_);
428              
429 0           $parser->_track_marker;
430 0           $parser->_track_font;
431 0           $parser->_track_left_margin;
432 0           $parser->_track_section_number;
433             }
434              
435              
436              
437             #######################################################################
438             # some applications, such as a pod viewer using Tk::Text, will need
439             # unique marker names for each element in the document. This method
440             # keeps a runnning counter for each type of element and concatenates
441             # the counter number to the element type to generate a unique marker name.
442             # Note that this marker is identical for start, text, and end.
443             # It is up to the OutputMarker method to concat the start or end string
444             # to generate a completely unique marker name. This marker name can then
445             # be inserted at the current 'insert' position. i.e. at the end of the
446             # document. OutputText will then insert the text at the end, and the
447             # marker will stay at the beginning of that text block permanently.
448             # this can provide a location to tie links to for jumping locations, etc.
449             #######################################################################
450             sub _track_marker
451             #######################################################################
452             {
453 0     0     my $parser=shift(@_);
454 0           my $element = $parser->GetAttribute('_element_type');
455              
456 0           my $marker_type = 'MARKER_'.$element.'_';
457              
458 0 0         unless(exists($parser->{_marker_counters}->{$marker_type}))
459             {
460 0           $parser->{_marker_counters}->{$marker_type}=1;
461             }
462              
463 0           my $counter = $parser->{_marker_counters}->{$marker_type}++;
464              
465 0           my $marker_name = $marker_type .'_'. $counter.'_';
466              
467 0           $parser->SetAttribute('_position_marker', $marker_name);
468              
469 0           $parser->OutputMarker;
470              
471              
472             }
473              
474             #######################################################################
475             # base class can override this to set marker if needed. (example: Tk::Text)
476             # Will want to create a marker based on the two following attributes
477             # marker_name = _position_marker . _start_end
478             # this will allow programs to "box" in text on either side with unique
479             # marker names.
480             #
481             # If your application needs a marker, simply insert the marker at the
482             # current 'insert' position. Use the 'insert' position for OutputText
483             # method as well, and all your text elements will be boxed by unique markers.
484             #
485             # if you dont need markers, then don't override this method and nothing
486             # will happen.
487             #######################################################################
488             sub OutputMarker
489             #######################################################################
490             {
491 0     0 0   my $parser = shift(@_);
492 0           my $position_marker = $parser->GetAttribute('_position_marker');
493 0           my $start_end = $parser->GetAttribute('_start_end');
494 0           my $marker_name = $position_marker . $start_end;
495              
496             # if you want to override this method, duplicate this method
497             # in your base class, and then do something with $marker_name here.
498              
499             }
500              
501             #######################################################################
502             #######################################################################
503             sub _track_font
504             #######################################################################
505             {
506 0     0     my $parser=shift(@_);
507 0           my $startend = $parser->GetAttribute('_start_end');
508 0           my $element = $parser->GetAttribute('_element_type');
509              
510 0 0         if($startend eq 'start')
511             {
512 0 0         if($parser->ExistsPreviousAttribute('_font_family'))
513             {
514 0           $parser->SetAttribute('_font_family',
515             $parser->GetPreviousAttribute('_font_family') );
516 0           $parser->SetAttribute('_font_size',
517             $parser->GetPreviousAttribute('_font_size') );
518 0           $parser->SetAttribute('_font_weight',
519             $parser->GetPreviousAttribute('_font_weight') );
520 0           $parser->SetAttribute('_font_slant',
521             $parser->GetPreviousAttribute('_font_slant') );
522 0           $parser->SetAttribute('_font_underline',
523             $parser->GetPreviousAttribute('_font_underline') );
524             }
525             else
526             {
527 0           $parser->SetAttribute('_font_family','lucida'); # lucida, courier
528 0           $parser->SetAttribute('_font_size', 4); # 1,2,3,4
529 0           $parser->SetAttribute('_font_weight', 'normal'); # normal, bold
530 0           $parser->SetAttribute('_font_slant', 'roman'); # roman, italic
531 0           $parser->SetAttribute('_font_underline', 'nounder'); # yesunder, nounder
532             }
533              
534 0 0         if(0) {}
    0          
    0          
    0          
    0          
535 0           elsif($element eq 'C')
536             {
537 0           $parser->SetAttribute('_font_family','courier');
538             }
539             elsif($element eq 'head')
540             {
541 0           my $hindex = $parser->GetAttribute('_head_index');
542 0           $parser->SetAttribute('_font_underline', 'yesunder');
543 0           $parser->SetAttribute('_font_size', $hindex);
544 0           $parser->SetAttribute('_font_weight', 'bold');
545             }
546             elsif($element eq 'I')
547             {
548 0           $parser->SetAttribute('_font_slant', 'italic');
549             }
550             elsif($element eq 'B')
551             {
552 0           $parser->SetAttribute('_font_weight', 'bold');
553             }
554              
555             elsif($element eq 'L')
556             {
557 0           $parser->SetAttribute('_font_underline', 'yesunder');
558             }
559              
560              
561             }
562             }
563              
564             #######################################################################
565             sub _current_font
566             #######################################################################
567             {
568 0     0     my $parser=shift(@_);
569 0           my $font_string =
570             ($parser->GetAttribute('_font_family'))
571             . ($parser->GetAttribute('_font_size'))
572             . ($parser->GetAttribute('_font_weight'))
573             . ($parser->GetAttribute('_font_slant'))
574             . ($parser->GetAttribute('_font_underline'))
575             ;
576              
577 0           return $font_string;
578             }
579              
580             #######################################################################
581             sub _track_left_margin
582             #######################################################################
583             {
584 0     0     my $parser=shift(@_);
585              
586 0           my $startend = $parser->GetAttribute('_start_end');
587              
588 0 0         if($parser->ExistsPreviousAttribute('_left_margin'))
589             {
590 0           $parser->SetAttribute
591             (
592             '_left_margin',
593             $parser->GetPreviousAttribute('_left_margin')
594             );
595             }
596             else
597             {
598 0           $parser->SetAttribute('_left_margin',0)
599             }
600              
601             # the 'indent' attribute comes from Pod::Simple
602             # if it exists, grab it and store it.
603             # it only exists on 'start' so need to keep it around for 'end'
604              
605 0 0         unless(exists($parser->{_accumulated_indent_values}))
606             {
607 0           $parser->{_accumulated_indent_values}=[];
608             }
609              
610              
611 0           my $indent=0;
612 0 0         if($startend eq 'start')
    0          
613             {
614 0 0         if($parser->ExistsAttribute('indent'))
    0          
615             {
616 0           $indent=$parser->GetAttribute('indent');
617             }
618             elsif(!($parser->ExistsAttribute('~type')))
619             {
620 0 0         if($parser->ExistsPreviousAttribute('~type'))
621             {
622 0           $indent += 4;
623             }
624             }
625              
626 0           push(@{$parser->{_accumulated_indent_values}}, $indent);
  0            
627             }
628              
629             elsif($startend eq 'end')
630             {
631 0           $indent = pop(@{$parser->{_accumulated_indent_values}});
  0            
632 0           $indent *= -1;
633             }
634              
635             # warn "indent is '$indent'";
636              
637 0           $parser->SetAttribute('_left_margin',
638             $parser->GetAttribute('_left_margin') + $indent);
639              
640             }
641              
642              
643             #######################################################################
644             sub _label_current_section
645             #######################################################################
646             {
647 0     0     my $parser=shift(@_);
648              
649 0           my $temp_ref = $parser->{_stack_of_section_numbers};
650 0           my @section_number;
651 0           my $object_to_label = $temp_ref->[-1];
652              
653 0           while(1)
654             {
655 0           push(@section_number, scalar(@$temp_ref));
656 0           $temp_ref = $temp_ref->[-1]->{Subparagraph};
657 0 0         last unless(scalar( @$temp_ref ));
658 0           $object_to_label = $temp_ref->[-1];
659             }
660              
661 0           my $section_string = join('.', @section_number) . ': ';
662 0           $object_to_label->{Section}=$section_string;
663              
664 0           return $section_string;
665             }
666              
667             #######################################################################
668             sub _new_toc_hash
669             #######################################################################
670             {
671 0     0     my $parser=shift(@_);
672 0           my $depth=shift(@_);
673              
674             # using a scalar to hold text so when take
675             # a reference, it will be a reference to a scalar,
676             # (which can be changed) rather than a reference
677             # to a literal
678 0           my $temp_text = 'This Paragraph number skipped';
679              
680 0           my $href=
681             {
682             TextRef => $temp_text,
683             Depth=>$depth,
684             Subparagraph => [],
685             };
686              
687 0           return $href;
688             }
689              
690             #######################################################################
691             sub _track_section_number
692             #######################################################################
693             {
694 0     0     my ($parser)=@_;
695              
696 0           my $element = $parser->GetAttribute('_element_type');
697 0           my $start_end = $parser->GetAttribute('_start_end');
698              
699 0 0 0       return unless( ($element eq 'head') and ($start_end eq 'start') );
700              
701 0 0         unless(exists($parser->{_stack_of_section_numbers}))
702             {
703 0           $parser->{_stack_of_section_numbers}=[];
704             }
705              
706 0           my $depth = $parser->GetAttribute('_head_index');
707              
708 0           my $href= $parser->_new_toc_hash($depth);
709              
710             ###############################################################
711             # first, figure out where to put the $href entry...
712             ###############################################################
713              
714 0           my $arr_ref = $parser->{_stack_of_section_numbers};
715              
716 0           for(my $cnt=1; $cnt<$depth; $cnt++)
717             {
718 0 0         unless(scalar(@$arr_ref))
719             {
720 0           my $temp= $parser->_new_toc_hash($depth);
721              
722             # push it onto end and label it
723 0           push(@$arr_ref, $temp);
724 0           $parser->_label_current_section;
725             }
726              
727 0           $arr_ref = $arr_ref->[-1]->{Subparagraph};
728             }
729              
730             # push it onto end and label it.
731 0           push(@$arr_ref,$href);
732 0           my $section_string = $parser->_label_current_section;
733              
734             # set an attribute to point to toc text
735             # this will allow someone to modify toc text later
736             # when toc text is actually a known value.
737 0           my $toc_text_ref = \$href->{TextRef};
738 0           $parser->SetAttribute('_toc_text_ref', $toc_text_ref);
739              
740 0           $parser->SetAttribute('_section_number', $section_string);
741             }
742              
743              
744              
745              
746             #######################################################################
747             # insert a dummy method here. subclass can override this method and
748             # have it do whatever it needs.
749             #######################################################################
750             sub OutputPodNewLine
751             #######################################################################
752             {
753 0     0 0   my $parser = shift(@_);
754              
755 0           print "calling Base default method for 'OutputPodNewLine'\n";
756             }
757              
758              
759             #######################################################################
760             # insert a dummy method here. subclass can override this method and
761             # have it do whatever it needs.
762             #######################################################################
763             sub OutputTocNewLine
764             #######################################################################
765             {
766 0     0 0   my $parser = shift(@_);
767              
768 0           print "calling Base default method for 'OutputTocNewLine'\n";
769             }
770              
771              
772              
773              
774             #######################################################################
775             #######################################################################
776             #######################################################################
777             #######################################################################
778             # this method is called by Pod::Simple when text is encountered.
779             # the handle_element_start method above makes sure that ALL attributes
780             # are current by the time the code enters _handle_text.
781             #######################################################################
782             #######################################################################
783             #######################################################################
784             #######################################################################
785             #######################################################################
786             sub _handle_text
787             #######################################################################
788             #######################################################################
789             #######################################################################
790             #######################################################################
791             #######################################################################
792             {
793 0     0     my $parser = shift(@_);
794              
795             #print Dumper \@_;
796 0           my $text = shift(@_);
797              
798 0           my $element = $parser->GetAttribute('_element_type');
799              
800             # put bullet in front of bulleted items
801 0 0         if($element eq 'item_bullet')
802             {
803 0           my $bullet = $parser->GetAttribute('~orig_content');
804 0           $text = $bullet.' '.$text;
805             }
806              
807 0           $parser->SetAttribute('_text_string', $text);
808              
809 0 0         if($parser->SearchHistoryForAttributeMatchingValue('_element_type', 'head'))
810             {
811 0           my $toc_text_ref = $parser->GetAttribute('_toc_text_ref');
812 0           $$toc_text_ref=$text;
813 0           $parser->OutputTocText;
814             }
815              
816             ###################################################################
817             # if a base class wishes to handle links differently,
818             # simply create a method called 'output_L'
819             # it will get called any time a link is encountered.
820             # 'output_L' could insert the text differently, adding
821             # a callback routine so the user can click on link and
822             # it will take the user to the file.
823             #
824             # otherwise, if no special handler exists, call normal OutputPodText.
825             ###################################################################
826 0           my $method = 'output_'.$element;
827              
828 0 0         if($parser->can($method))
829             {
830 0           $parser->$method;
831             }
832             else
833             {
834 0           $parser->OutputPodText;
835             }
836             }
837              
838             #######################################################################
839             # insert a dummy method here. subclass can override this method and
840             # have it do whatever it needs.
841             #######################################################################
842             sub OutputPodText
843             #######################################################################
844             {
845 0     0 0   my $parser = shift(@_);
846 0           my $text_string = $parser->GetAttribute('_text_string');
847              
848 0           print "calling Base default method for 'OutputPodText'\n";
849 0           print "$text_string \n";
850             }
851              
852              
853             #######################################################################
854             sub OutputTocText
855             #######################################################################
856             {
857 0     0 0   my $parser = shift(@_);
858 0           my $text_string = $parser->GetAttribute('_text_string');
859              
860 0           print "calling Base default method for 'OutputTocText'\n";
861 0           print "$text_string \n";
862              
863             }
864              
865              
866              
867              
868              
869              
870             #######################################################################
871             #######################################################################
872             #######################################################################
873             #######################################################################
874             sub DESTROY
875             #######################################################################
876             #######################################################################
877             #######################################################################
878             {
879 0     0     return;
880              
881 0           my $parser = shift(@_);
882 0           my $toc = $parser->{_stack_of_section_numbers};
883 0           print Dumper $toc;
884             }
885              
886             #######################################################################
887             #######################################################################
888             #######################################################################
889              
890             1;
891             __END__