File Coverage

blib/lib/HTML/TocGenerator.pm
Criterion Covered Total %
statement 492 570 86.3
branch 103 146 70.5
condition 27 41 65.8
subroutine 93 108 86.1
pod 8 19 42.1
total 723 884 81.7


line stmt bran cond sub pod time code
1             #=== HTML::TocGenerator =======================================================
2             # function: Generate 'HTML::Toc' table of contents.
3             # note: - 'TT' is an abbrevation of 'TocToken'.
4              
5              
6             package HTML::TocGenerator;
7              
8              
9 12     12   9098 use strict;
  12         24  
  12         507  
10 12     12   23892 use HTML::Parser;
  12         101196  
  12         687  
11              
12              
13             BEGIN {
14 12     12   145 use vars qw(@ISA $VERSION);
  12         23  
  12         801  
15              
16 12     12   28 $VERSION = '1.12';
17              
18 12         442 @ISA = qw(HTML::Parser);
19             }
20              
21              
22             # Warnings
23 12     12   67 use constant WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS => 2;
  12         22  
  12         986  
24              
25              
26 12     12   225 use constant TOC_TOKEN_ID => 0;
  12         24  
  12         485  
27 12     12   73 use constant TOC_TOKEN_INCLUDE => 1;
  12         18  
  12         501  
28 12     12   51 use constant TOC_TOKEN_EXCLUDE => 2;
  12         21  
  12         497  
29 12     12   52 use constant TOC_TOKEN_TOKENS => 3;
  12         19  
  12         443  
30 12     12   54 use constant TOC_TOKEN_GROUP => 4;
  12         18  
  12         437  
31 12     12   50 use constant TOC_TOKEN_TOC => 5;
  12         34  
  12         491  
32              
33 12     12   53 use constant CONTAINMENT_INCLUDE => 0;
  12         24  
  12         470  
34 12     12   54 use constant CONTAINMENT_EXCLUDE => 1;
  12         26  
  12         487  
35              
36             # Token types
37 12     12   54 use constant TT_TAG_BEGIN => 0;
  12         21  
  12         492  
38 12     12   51 use constant TT_TAG_END => 1;
  12         28  
  12         503  
39 12     12   52 use constant TT_TAG_TYPE_END => 2;
  12         26  
  12         464  
40 12     12   55 use constant TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
  12         16  
  12         479  
41 12     12   57 use constant TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
  12         16  
  12         654  
42 12     12   136 use constant TT_INCLUDE_ATTRIBUTES_END => 5;
  12         25  
  12         518  
43 12     12   63 use constant TT_EXCLUDE_ATTRIBUTES_END => 6;
  12         18  
  12         491  
44 12     12   58 use constant TT_GROUP => 7;
  12         18  
  12         558  
45 12     12   58 use constant TT_TOC => 8;
  12         22  
  12         483  
46 12     12   1403 use constant TT_ATTRIBUTES_TOC => 9;
  12         21  
  12         676  
47              
48 12     12   60 use constant TT_TOKENTYPE_START => 0;
  12         19  
  12         623  
49 12     12   56 use constant TT_TOKENTYPE_END => 1;
  12         17  
  12         480  
50 12     12   53 use constant TT_TOKENTYPE_TEXT => 2;
  12         24  
  12         549  
51 12     12   62 use constant TT_TOKENTYPE_COMMENT => 3;
  12         27  
  12         564  
52 12     12   55 use constant TT_TOKENTYPE_DECLARATION => 4;
  12         17  
  12         70049  
53              
54              
55 12     12   61 END {}
56              
57              
58             #--- HTML::TocGenerator::new() ------------------------------------------------
59             # function: Constructor
60              
61             sub new {
62             # Get arguments
63 42     42 1 191 my ($aType) = @_;
64 42         264 my $self = $aType->SUPER::new;
65             # Bias to not generate ToC
66 42         2787 $self->{_doGenerateToc} = 0;
67             # Bias to not use global groups
68 42         95 $self->{_doUseGroupsGlobal} = 0;
69             # Output
70 42         76 $self->{_doReleaseElement} = 1;
71 42         130 $self->{output} = "";
72             # Reset internal variables
73 42         180 $self->_resetBatchVariables();
74              
75 42         160 $self->{options} = {};
76              
77 42         151 return $self;
78             } # new()
79              
80              
81             #--- HTML::TocGenerator::_deinitializeBatch() ---------------------------------
82              
83             sub _deinitializeBatch() {
84             # Get arguments
85 100     100   185 my ($self) = @_;
86             } # _deinitializeBatch()
87              
88              
89             #--- HTML::TocGenerator::_deinitializeExtenderBatch() -------------------------
90              
91             sub _deinitializeExtenderBatch() {
92             # Get arguments
93 94     94   128 my ($self) = @_;
94             # Do general batch deinitialization
95 94         316 $self->_deinitializeBatch();
96             # Indicate end of ToC generation
97 94         166 $self->{_doGenerateToc} = 0;
98             # Reset batch variables
99 94         293 $self->_resetBatchVariables();
100             } # _deinitializeExtenderBatch()
101              
102              
103             #--- HTML::TocGenerator::_deinitializeGeneratorBatch() ------------------------
104              
105             sub _deinitializeGeneratorBatch() {
106             # Get arguments
107 88     88   158 my ($self) = @_;
108             # Do 'extender' batch deinitialization
109 88         289 $self->_deinitializeExtenderBatch();
110             } # _deinitializeBatchGenerator()
111              
112              
113             #--- HTML::TocGenerator::_doesHashContainHash() -------------------------------
114             # function: Determines whether hash1 matches regular expressions of hash2.
115             # args: - $aHash1
116             # - $aHash2
117             # - $aContainmentType: 0 (include) or 1 (exclude)
118             # returns: True (1) if hash1 satisfies hash2, 0 if not. For example, with the
119             # following hashes:
120             #
121             # %hash1 = { %hash2 = {
122             # 'class' => 'header' 'class' => '^h'
123             # 'id' => 'intro' }
124             # }
125             #
126             # the routine will return 1 if 'aContainmentType' equals 0, cause
127             # 'hash1' satisfies the conditions of 'hash2'. The routine will
128             # return 0 if 'aContainmentType' equals 1, cause 'hash1' doesn't
129             # exclude the conditions of 'hash2'.
130             # note: Class function.
131              
132             sub _doesHashContainHash {
133             # Get arguments
134 884     884   1877 my ($aHash1, $aHash2, $aContainmentType) = @_;
135             # Local variables
136 884         973 my ($key1, $value1, $key2, $value2, $result);
137             # Bias to success
138 884         1247 $result = 1;
139             # Loop through hash2
140 884         2769 HASH2: while (($key2, $value2) = each %$aHash2) {
141             # Yes, values are available;
142             # Get value1
143 286         536 $value1 = $aHash1->{$key2};
144             # Does value1 match criteria of value2?
145 286 100 100     3077 if (defined($value1) && $value1 =~ m/$value2/) {
146             # Yes, value1 matches criteria of value2;
147             # Containment type was exclude?
148 93 100       339 if ($aContainmentType == CONTAINMENT_EXCLUDE) {
149             # Yes, containment type was exclude;
150             # Indicate condition fails
151 44         62 $result = 0;
152             # Reset 'each' iterator which we're going to break
153 44         61 keys %$aHash2;
154             # Break loop
155 44         75 last HASH2;
156             }
157             }
158             else {
159             # No, value1 didn't match criteria of value2;
160             # Containment type was include?
161 193 100       449 if ($aContainmentType == CONTAINMENT_INCLUDE) {
162             # Yes, containment type was include;
163             # Indicate condition fails
164 170         210 $result = 0;
165             # Reset 'each' iterator which we're going to break
166 170         224 keys %$aHash2;
167             # Break loop
168 170         280 last HASH2;
169             }
170             }
171             }
172             # Return value
173 884         4757 return $result;
174             } # _doesHashContainHash()
175              
176              
177             #--- HTML::TocGenerator::_extend() --------------------------------------------
178             # function: Extend ToC.
179             # - $aString: String to parse.
180              
181             sub _extend {
182             # Get arguments
183 60     60   113 my ($self, $aFile) = @_;
184             # Local variables
185 60         76 my ($file);
186             # Parse string
187 60         206 $self->parse($aFile);
188             # Flush remaining buffered text
189 60         406 $self->eof();
190             } # _extend()
191              
192              
193             #--- HTML::TocGenerator::_extendFromFile() ------------------------------------
194             # function: Extend ToC.
195             # - $aFile: (reference to array of) file to parse.
196              
197             sub _extendFromFile {
198             # Get arguments
199 34     34   58 my ($self, $aFile) = @_;
200             # Local variables
201 34         156 my ($file, @files);
202             # Dereference array reference or make array of file specification
203 34 100       142 @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile);
204             # Loop through files
205 34         67 foreach $file (@files) {
206             # Store filename
207 43         89 $self->{_currentFile} = $file;
208             # Parse file
209 43         202 $self->parse_file($file);
210             # Flush remaining buffered text
211 43         317 $self->eof();
212             }
213             } # _extendFromFile()
214              
215              
216             #--- HTML::TocGenerator::_formatHeadingLevel() --------------------------------
217             # function: Format heading level.
218             # args: - $aLevel: Level of current heading
219             # - $aClass: Class of current heading
220             # - $aGroup: Group of current heading
221             # - $aToc: Toc of current heading
222              
223             sub _formatHeadingLevel {
224             # Get arguments
225 313     313   464 my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
226             # Local variables
227 313         339 my ($result, $headingNumber, $numberingStyle);
228              
229 313   100     585 $headingNumber = $self->_getGroupIdManager($aToc)->
230             {levels}{$aClass}[$aLevel - 1] || 0;
231              
232             # Alias numbering style of current group
233 313         510 $numberingStyle = $aGroup->{numberingStyle};
234              
235             SWITCH: {
236 313 100       662 if ($numberingStyle eq "decimal") {
  313         732  
237 282         319 $result = $headingNumber;
238 282         439 last SWITCH;
239             }
240 31 100       83 if ($numberingStyle eq "lower-alpha") {
241 7         17 $result = chr($headingNumber + ord('a') - 1);
242 7         15 last SWITCH;
243             }
244 24 50       60 if ($numberingStyle eq "upper-alpha") {
245 24         50 $result = chr($headingNumber + ord('A') - 1);
246 24         44 last SWITCH;
247             }
248 0 0       0 if ($numberingStyle eq "lower-roman") {
249 0         0 require Roman;
250 0         0 $result = Roman::roman($headingNumber);
251 0         0 last SWITCH;
252             }
253 0 0       0 if ($numberingStyle eq "upper-roman") {
254 0         0 require Roman;
255 0         0 $result = Roman::Roman($headingNumber);
256 0         0 last SWITCH;
257             }
258 0         0 die "Unknown case: $numberingStyle";
259             }
260             # Return value
261 313         1290 return $result;
262             } # _formatHeadingLevel()
263              
264              
265             #--- HTML::TocGenerator::_formatTocNode() -------------------------------------
266             # function: Format heading node.
267             # args: - $aLevel: Level of current heading
268             # - $aClass: Class of current heading
269             # - $aGroup: Group of current heading
270             # - $aToc: Toc of current heading
271              
272             sub _formatTocNode {
273             # Get arguments
274 236     236   397 my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
275             # Local variables
276 236         274 my ($result, $level, $levelGroups);
277              
278             # Alias 'levelGroups' of right 'groupId'
279 236         583 $levelGroups = $aToc->{_levelGroups}{$aGroup->{'groupId'}};
280             # Loop through levels
281 236         674 for ($level = 1; $level <= $aLevel; $level++) {
282             # If not first level, add dot
283 313 100       627 $result = ($result ? $result . "." : $result);
284             # Format heading level using argument group
285 313         958 $result .= $self->_formatHeadingLevel(
286 313         431 $level, $aClass, @{$levelGroups}[$level - 1], $aToc
287             );
288             }
289             # Return value
290 236         606 return $result;
291             } # _formatTocNode()
292            
293            
294             #--- HTML::TocGenerator::_generate() ------------------------------------------
295             # function: Generate ToC.
296             # args: - $aString: Reference to string to parse
297              
298             sub _generate {
299             # Get arguments
300 58     58   95 my ($self, $aString) = @_;
301             # Local variables
302 58         88 my ($toc);
303             # Loop through ToCs
304 58         88 foreach $toc (@{$self->{_tocs}}) {
  58         148  
305             # Clear ToC
306 58         226 $toc->clear();
307             }
308             # Extend ToCs
309 58         292 $self->_extend($aString);
310             } # _generate()
311              
312              
313             #--- HTML::TocGenerator::_generateFromFile() ----------------------------------
314             # function: Generate ToC.
315             # args: - $aFile: (reference to array of) file to parse.
316              
317             sub _generateFromFile {
318             # Get arguments
319 30     30   57 my ($self, $aFile) = @_;
320             # Local variables
321 30         42 my ($toc);
322             # Loop through ToCs
323 30         40 foreach $toc (@{$self->{_tocs}}) {
  30         152  
324             # Clear ToC
325 39         127 $toc->clear();
326             }
327             # Extend ToCs
328 30         145 $self->_extendFromFile($aFile);
329             } # _generateFromFile()
330              
331              
332             #--- HTML::TocGenerator::_getGroupIdManager() ---------------------------------
333             # function: Get group id manager.
334             # args: - $aToc: Active ToC.
335             # returns: Group id levels.
336              
337             sub _getGroupIdManager {
338             # Get arguments
339 549     549   663 my ($self, $aToc) = @_;
340             # Local variables
341 549         576 my ($result);
342             # Global groups?
343 549 100       1159 if ($self->{options}{'doUseGroupsGlobal'}) {
344             # Yes, global groups;
345 184         211 $result = $self;
346             }
347             else {
348             # No, local groups;
349 365         461 $result = $aToc;
350             }
351             # Return value
352 549         1574 return $result;
353             } # _getGroupIdManager()
354              
355              
356             #--- HTML::TocGenerator::_initializeBatch() -----------------------------------
357             # function: Initialize batch. This function is called once when a parse batch
358             # is started.
359             # args: - $aTocs: Reference to array of tocs.
360              
361             sub _initializeBatch {
362             # Get arguments
363 100     100   162 my ($self, $aTocs) = @_;
364             # Local variables
365 100         236 my ($toc);
366              
367             # Store reference to tocs
368            
369             # Is ToC specification reference to array?
370 100 100       372 if (ref($aTocs) =~ m/ARRAY/) {
371             # Yes, ToC specification is reference to array;
372             # Store array reference
373 6         15 $self->{_tocs} = $aTocs;
374             }
375             else {
376             # No, ToC specification is reference to ToC object;
377             # Wrap reference in array reference, containing only one element
378 94         261 $self->{_tocs} = [$aTocs];
379             }
380             # Loop through ToCs
381 100         179 foreach $toc (@{$self->{_tocs}}) {
  100         242  
382             # Parse ToC options
383 109         383 $toc->parseOptions();
384             }
385             } # _initializeBatch()
386              
387              
388             #--- HTML::TocGenerator::_initializeExtenderBatch() --------------------------
389             # function: Initialize 'extender' batch. This function is called once when a
390             # parse batch is started.
391             # args: - $aTocs: Reference to array of tocs.
392              
393             sub _initializeExtenderBatch {
394             # Get arguments
395 94     94   147 my ($self, $aTocs) = @_;
396             # Do general batch initialization
397 94         314 $self->_initializeBatch($aTocs);
398             # Parse ToC options
399 94         399 $self->_parseTocOptions();
400             # Indicate start of batch
401 94         337 $self->{_doGenerateToc} = 1;
402             } # _initializeExtenderBatch()
403              
404              
405             #--- HTML::TocGenerator::_initializeGeneratorBatch() --------------------------
406             # function: Initialize generator batch. This function is called once when a
407             # parse batch is started.
408             # args: - $aTocs: Reference to array of tocs.
409             # - $aOptions: optional options
410              
411             sub _initializeGeneratorBatch {
412             # Get arguments
413 88     88   160 my ($self, $aTocs, $aOptions) = @_;
414             # Add invocation options
415 88         224 $self->setOptions($aOptions);
416             # Option 'doUseGroupsGlobal' specified?
417 88 100       301 if (!defined($self->{options}{'doUseGroupsGlobal'})) {
418             # No, options 'doUseGroupsGlobal' not specified;
419             # Default to no 'doUseGroupsGlobal'
420 35         80 $self->{options}{'doUseGroupsGlobal'} = 0;
421             }
422             # Global groups?
423 88 100       280 if ($self->{options}{'doUseGroupsGlobal'}) {
424             # Yes, global groups;
425             # Reset groups and levels
426 4         23 $self->_resetStackVariables();
427             }
428             # Do 'extender' batch initialization
429 88         333 $self->_initializeExtenderBatch($aTocs);
430             } # _initializeGeneratorBatch()
431              
432              
433             #--- HTML::TocGenerator::_linkTocToToken() ------------------------------------
434             # function: Link ToC to token.
435             # args: - $aToc: ToC to add token to.
436             # - $aFile
437             # - $aGroupId
438             # - $aLevel
439             # - $aNode
440             # - $aGroupLevel
441             # - $aLinkType
442             # - $aTokenAttributes: reference to hash containing attributes of
443             # start token
444              
445             sub _linkTocToToken {
446             # Get arguments
447             my (
448 206     206   453 $self, $aToc, $aFile, $aGroupId, $aLevel, $aNode, $aGroupLevel,
449             $aDoLinkToId, $aTokenAttributes
450             ) = @_;
451             # Local variables
452 206         255 my ($anchorName, $children, $file, $groupId, $level, $node, $text);
453 0         0 my ($doInsertAnchor, $doInsertId);
454              
455             # Fill local arguments to be used by templates
456 206         237 $file = $aFile;
457 206         250 $groupId = $aGroupId;
458 206         237 $level = $aLevel;
459 206         276 $node = $aNode;
460 206 50       557 $text = defined($self->{_holdText}) ? $self->{_holdText} : '';
461 206 50       470 $children = defined($self->{_holdChildren}) ? $self->{_holdChildren} : '';
462            
463             # Assemble anchor name
464 31         107 $anchorName =
465             ref($aToc->{_templateAnchorName}) eq "CODE" ?
466 206 100       11685 &{$aToc->{_templateAnchorName}}(
467             $aFile, $aGroupId, $aLevel, $aNode, $text, $children
468             ) :
469             eval($aToc->{_templateAnchorName});
470              
471             # Bias to insert anchor name
472 206         2883 $doInsertAnchor = 1;
473 206         251 $doInsertId = 0;
474             # Link to 'id'?
475 206 50       414 if ($aDoLinkToId) {
476             # Yes, link to 'id';
477             # Indicate to insert anchor id
478 0         0 $doInsertAnchor = 0;
479 0         0 $doInsertId = 1;
480             # Id attribute is available?
481 0 0       0 if (defined($aTokenAttributes->{id})) {
482             # Yes, id attribute is available;
483             # Use existing ids?
484 0 0       0 if ($aToc->{options}{'doUseExistingIds'}) {
485             # Yes, use existing ids;
486             # Use existing id
487 0         0 $anchorName = $aTokenAttributes->{id};
488             # Indicate to not insert id
489 0         0 $doInsertId = 0;
490             }
491             } # if
492             } else {
493             # No, link to 'name';
494             # Anchor name is currently active?
495 206 50       583 if (defined($self->{_activeAnchorName})) {
496             # Yes, anchor name is currently active;
497             # Use existing anchors?
498 0 0       0 if ($aToc->{options}{'doUseExistingAnchors'}) {
499             # Yes, use existing anchors;
500             # Use existing anchor name
501 0         0 $anchorName = $self->{_activeAnchorName};
502             # Indicate to not insert anchor name
503 0         0 $doInsertAnchor = 0;
504             } else {
505             # No, don't use existing anchors; insert new anchor;
506             #
507             }
508             }
509             }
510              
511             # Add reference to ToC
512 1         5 $aToc->{_toc} .=
513             ref($aToc->{_templateAnchorHrefBegin}) eq "CODE" ?
514 206 100       12255 &{$aToc->{_templateAnchorHrefBegin}}(
515             $aFile, $aGroupId, $aLevel, $aNode, $anchorName
516             ) :
517             eval($aToc->{_templateAnchorHrefBegin});
518              
519             # Bias to not output anchor name end
520 206         713 $self->{_doOutputAnchorNameEnd} = 0;
521             # Must anchor be inserted?
522 206 50       1244 if ($doInsertAnchor) {
523             # Yes, anchor must be inserted;
524             # Allow adding of anchor name begin token to text by calling
525             # 'anchorNameBegin' method
526 1         5 $self->afterAnchorNameBegin(
527             $self->anchorNameBegin(
528             ref($aToc->{_templateAnchorNameBegin}) eq "CODE" ?
529 206 100       10650 &{$aToc->{_templateAnchorNameBegin}}(
530             $aFile, $aGroupId, $aLevel, $aNode, $anchorName
531             ) :
532             eval($aToc->{_templateAnchorNameBegin}),
533             $aToc
534             ), $aToc
535             );
536             }
537              
538             # Must anchorId attribute be inserted?
539 206 50       1381 if ($doInsertId) {
540             # Yes, anchorId attribute must be inserted;
541             # Allow adding of anchorId attribute to text by calling 'anchorId'
542             # method
543 0         0 $self->anchorId($anchorName);
544             }
545             } # _linkTocToToken()
546              
547              
548             #--- HTML::TocGenerator::_outputAnchorNameEndConditionally() ------------------
549             # function: Output 'anchor name end' if necessary
550             # args: - $aToc: ToC of which 'anchor name end' must be output.
551              
552             sub _outputAnchorNameEndConditionally {
553             # Get arguments
554 206     206   372 my ($self, $aToc) = @_;
555             # Must anchor name end be output?
556 206 100       564 if ($self->{_doOutputAnchorNameEnd}) {
557             # Yes, output anchor name end;
558             # Allow adding of anchor to text by calling 'anchorNameEnd'
559             # method
560 0         0 $self->anchorNameEnd(
561             ref($aToc->{_templateAnchorNameEnd}) eq "CODE" ?
562 173 50       9261 &{$aToc->{_templateAnchorNameEnd}} :
563             eval($aToc->{_templateAnchorNameEnd}),
564             $aToc
565             );
566             }
567             } # _outputAnchorNameEndConditionally()
568              
569              
570             #--- HTML::TocGenerator::_parseTocOptions() -----------------------------------
571             # function: Parse ToC options.
572              
573             sub _parseTocOptions {
574             # Get arguments
575 94     94   145 my ($self) = @_;
576             # Local variables
577 94         138 my ($toc, $group, $tokens, $tokenType, $i);
578             # Create parsers for ToC tokens
579 94         228 $self->{_tokensTocBegin} = [];
580 94         618 my $tokenTocBeginParser = HTML::_TokenTocBeginParser->new(
581             $self->{_tokensTocBegin}
582             );
583 94         497 my $tokenTocEndParser = HTML::_TokenTocEndParser->new();
584             # Loop through ToCs
585 94         153 foreach $toc (@{$self->{_tocs}}) {
  94         256  
586             # Reference parser ToC to current ToC
587 103         312 $tokenTocBeginParser->setToc($toc);
588             # Loop through 'tokenToToc' groups
589 103         125 foreach $group (@{$toc->{options}{'tokenToToc'}}) {
  103         285  
590             # Reference parser group to current group
591 478         1033 $tokenTocBeginParser->setGroup($group);
592             # Parse 'tokenToToc' group
593 478         1074 $tokenTocBeginParser->parse($group->{'tokenBegin'});
594             # Flush remaining buffered text
595 478         1348 $tokenTocBeginParser->eof();
596 478         1964 $tokenTocEndParser->parse(
597             $group->{'tokenEnd'},
598             $tokenTocBeginParser->{_lastAddedToken},
599             $tokenTocBeginParser->{_lastAddedTokenType}
600             );
601             # Flush remaining buffered text
602 478         3609 $tokenTocEndParser->eof();
603             }
604             }
605             } # _parseTocOptions()
606              
607              
608             #--- HTML::TocGenerator::_processTocEndingToken() -----------------------------
609             # function: Process ToC-ending-token.
610             # args: - $aTocToken: token which acts as ToC-ending-token.
611              
612             sub _processTocEndingToken {
613             # Get arguments
614 236     236   501 my ($self, $aTocToken) = @_;
615             # Local variables
616 236         265 my ($text, $toc);
617             # Aliases
618 236         310 $toc = $aTocToken->[TT_TOC];
619              
620 236         429 $self->{_doReleaseElement} = 1;
621             # Process entire ToC element
622 236         1020 $self->_processTocStartingToken(
623             $self->{_holdTocStartToken},
624             $self->{_holdBeginTokenType},
625             $self->{_holdBeginTokenAttributes},
626             $self->{_holdBeginTokenOrig}
627             );
628              
629 236         643 $self->{_holdTocText} =~ s/\s*\n\s*/ /g;
630 236         505 $toc->{_toc} .= $self->{_holdTocText};
631              
632 236         370 $self->{_holdTocStartToken} = undef;
633 236         8754 $self->{_holdBeginTokenType} = undef;
634 236         343 $self->{_holdBeginTokenAttributes} = undef;
635 236         413 $self->{_holdBeginTokenOrig} = undef;
636 236         383 $self->{_holdText} = undef;
637 236         279 $self->{_holdTocText} = undef;
638 236         310 $self->{_holdChildren} = undef;
639              
640             # Link ToC to tokens?
641 236 100       642 if ($toc->{options}{'doLinkToToken'}) {
642             # Yes, link ToC to tokens;
643             # Add anchor href end
644 0         0 $toc->{_toc} .=
645             (ref($toc->{_templateAnchorHrefEnd}) eq "CODE") ?
646 206 50       9996 &{$toc->{_templateAnchorHrefEnd}} :
647             eval($toc->{_templateAnchorHrefEnd});
648              
649             # Output anchor name end only if necessary
650 206         834 $self->_outputAnchorNameEndConditionally($toc);
651             }
652             } # _processTocEndingToken()
653              
654              
655             #--- HTML::TocGenerator::_processTocStartingToken() ---------------------------
656             # function: Process ToC-starting-token.
657             # args: - $aTocToken: token which acts as ToC-starting-token.
658             # - $aTokenType: type of token. Can be either TT_TOKENTYPE_START,
659             # _END, _TEXT, _COMMENT or _DECLARATION.
660             # - $aTokenAttributes: reference to hash containing attributes of
661             # currently parsed token
662             # - $aTokenOrig: reference to original token
663              
664             sub _processTocStartingToken {
665             # Get arguments
666 236     236   391 my ($self, $aTocToken, $aTokenType, $aTokenAttributes, $aTokenOrig) = @_;
667             # Local variables
668 236         271 my ($i, $level, $doLinkToId, $node, $groupLevel);
669 0         0 my ($file, $tocTokenId, $groupId, $toc, $attribute);
670             # Aliases
671 236         414 $file = $self->{_currentFile};
672 236         301 $toc = $aTocToken->[TT_TOC];
673 236         375 $level = $aTocToken->[TT_GROUP]{'level'};
674 236         378 $groupId = $aTocToken->[TT_GROUP]{'groupId'};
675              
676 236 50       673 $doLinkToId = (defined($aTocToken->[TT_GROUP]{'doLinkToId'})) ?
677             $aTocToken->[TT_GROUP]{'doLinkToId'} : $toc->{options}{'doLinkToId'};
678            
679             # Link to 'id' and tokenType isn't 'start'?
680 236 50 33     599 if (($doLinkToId) && ($aTokenType != TT_TOKENTYPE_START)) {
681             # Yes, link to 'id' and tokenType isn't 'start';
682             # Indicate to *not* link to 'id'
683 0         0 $doLinkToId = 0;
684             }
685              
686 236 50       543 if (ref($level) eq "CODE") {
687 0         0 $level = &$level($self->{_currentFile}, $node);
688             }
689 236 50       469 if (ref($groupId) eq "CODE") {
690 0         0 $groupId = &$groupId($self->{_currentFile}, $node);
691             }
692              
693             # Determine class level
694              
695 236         653 my $groupIdManager = $self->_getGroupIdManager($toc);
696             # Known group?
697 236 100       684 if (!exists($groupIdManager->{groupIdLevels}{$groupId})) {
698             # No, unknown group;
699             # Add group
700 107         395 $groupIdManager->{groupIdLevels}{$groupId} = keys(
701 107         134 %{$groupIdManager->{groupIdLevels}}
702             ) + 1;
703             }
704 236         541 $groupLevel = $groupIdManager->{groupIdLevels}{$groupId};
705              
706             # Increase level
707 236         1372 $groupIdManager->{levels}{$groupId}[$level - 1] += 1;
708             # Reset remaining levels of same group
709 236         375 for ($i = $level; $i < @{$groupIdManager->{levels}{$groupId}}; $i++) {
  269         992  
710 33         85 $groupIdManager->{levels}{$groupId}[$i] = 0;
711             }
712              
713             # Assemble numeric string indicating current level
714 236         874 $node = $self->_formatTocNode(
715             $level, $groupId, $aTocToken->[TT_GROUP], $toc
716             );
717              
718             # Add newline if _toc not empty
719 236 100       615 if ($toc->{_toc}) {
720 142         228 $toc->{_toc} .= "\n";
721             }
722              
723             # Add toc item info
724 236         996 $toc->{_toc} .= "$level $groupLevel $groupId $node " .
725             $groupIdManager->{levels}{$groupId}[$level - 1] . " ";
726              
727             # Add value of 'id' attribute if available
728 236 50       551 if (defined($aTokenAttributes->{id})) {
729 0         0 $toc->{_toc} .= $aTokenAttributes->{id};
730             }
731 236         408 $toc->{_toc} .= " ";
732              
733             # Number tokens?
734 236 100 100     1745 if (
      66        
735             $aTocToken->[TT_GROUP]{'doNumberToken'} ||
736             (
737             ! defined($aTocToken->[TT_GROUP]{'doNumberToken'}) &&
738             $toc->{options}{'doNumberToken'}
739             )
740             ) {
741             # Yes, number tokens;
742             # Add number by calling 'number' method
743 51         179 $self->number(
744             $self->formatNumber(
745             ref($toc->{_templateTokenNumber}) eq "CODE" ?
746 88 100       3281 &{$toc->{_templateTokenNumber}}(
747             $node, $groupId, $file, $groupLevel, $level, $toc
748             ) :
749             eval($toc->{_templateTokenNumber}),
750             $toc
751             )
752             );
753             } # if
754              
755             # Link ToC to tokens?
756 236 100       791 if ($toc->{options}{'doLinkToToken'}) {
757             # Yes, link ToC to tokens;
758             # Link ToC to token
759 206         645 $self->_linkTocToToken(
760             $toc, $file, $groupId, $level, $node, $groupLevel, $doLinkToId,
761             $aTokenAttributes, $self->{_holdChildren}
762             );
763             } # if
764              
765             # Must attribute be used as ToC text?
766 236 100       941 if (defined($aTocToken->[TT_ATTRIBUTES_TOC])) {
767             # Yes, attribute must be used as ToC text;
768             # Loop through attributes
769 5         6 foreach $attribute (@{$aTocToken->[TT_ATTRIBUTES_TOC]}) {
  5         12  
770             # Attribute is available?
771 5 50       13 if (defined($$aTokenAttributes{$attribute})) {
772             # Yes, attribute is available;
773             # Add attribute value to ToC
774 5         16 $self->_processTocText($$aTokenAttributes{$attribute}, $toc);
775             }
776             else {
777             # No, attribute isn't available;
778             # Show warning
779 0         0 $self->_showWarning(
780             WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS,
781             [$attribute, $$aTokenOrig]
782             );
783             }
784             # Output anchor name end only if necessary
785             #$self->_outputAnchorNameEndConditionally($toc);
786             }
787             }
788             } # _processTocStartingToken()
789              
790              
791             #--- HTML::TocGenerator::_processTocText() ------------------------------------
792             # function: This function processes text which must be added to the preliminary
793             # (non-formatted) ToC.
794             # args: - $aText: Text to add to ToC.
795             # - $aToc: ToC to add text to.
796              
797             sub _processTocText {
798             # Get arguments
799 238     238   381 my ($self, $aText, $aToc) = @_;
800             # Add text to ToC
801 238 50       532 if (defined($self->{_holdTocText})) {
802 238         530 $self->{_holdTocText} .= $aText;
803             } else {
804             # Remove possible newlines from text
805 0         0 $aText =~ s/\s*\n\s*/ /g;
806 0         0 $aToc->{_toc} .= $aText;
807             } # if
808             } # _processTocText()
809              
810              
811             #--- HTML::TocGenerator::_processTocTokenChildren() --------------------
812             # function: This function processes children which resides inside a ToC token.
813             # args: - $aText
814             # - $aToc: ToC to which token belongs
815              
816             sub _processTocTokenChildren {
817             # Get arguments
818 504     504   1201 my ($self, $aText, $aToc) = @_;
819             # Must children be put on hold?
820 504 100       2364 if (defined($self->{_holdChildren})) {
821             # Yes, children must be put on hold;
822             # Add children to hold buffer
823 2         11 $self->{_holdChildren} .= $aText;
824             } # if
825             } # _processTocTokenChildren()
826              
827              
828             #--- HTML::TocGenerator::_processTocTokenText() ---------------------------
829             # function: This function processes text which resides inside a ToC token.
830             # args: - $aText
831             # - $aToc: ToC to which token belongs
832              
833             sub _processTocTokenText {
834             # Get arguments
835 233     233   359 my ($self, $aText, $aToc) = @_;
836             # Must text be put on hold?
837 233 50       633 if (defined($self->{_holdText})) {
838             # Yes, text must be put on hold;
839             # Add text to hold buffers
840 233         349 $self->{_holdText} .= $aText;
841 233         865 $self->{_holdChildren} .= $aText;
842             } # if
843             } # _processTocTokenText()
844              
845              
846             #--- HTML::TocGenerator::_processTokenAsTocEndingToken() ----------------------
847             # function: Check for token being a token to use for triggering the end of
848             # a ToC line and process it accordingly.
849             # args: - $aTokenType: type of token: 'start', 'end', 'comment' or 'text'.
850             # - $aTokenId: token id of currently parsed token
851              
852             sub _processTokenAsTocEndingToken {
853             # Get arguments
854 924     924   1425 my ($self, $aTokenType, $aTokenId) = @_;
855             # Local variables
856 924         1069 my ($i, $tokenId, $toc, $tokens);
857             # Loop through dirty start tokens
858 924         1543 $i = 0;
859              
860             # Alias token array of right type
861 924         1429 $tokens = $self->{_tokensTocEnd}[$aTokenType];
862             # Loop through token array
863 924         3541 while ($i < scalar @$tokens) {
864             # Aliases
865 258         639 $tokenId = $tokens->[$i][TT_TAG_END];
866             # Does current end tag equals dirty tag?
867 258 100       534 if ($aTokenId eq $tokenId) {
868             # Yes, current end tag equals dirty tag;
869             # Process ToC-ending-token
870 231         690 $self->_processTocEndingToken($tokens->[$i]);
871             # Remove dirty tag from array, automatically advancing to
872             # next token
873 231         1189 splice(@$tokens, $i, 1);
874             }
875             else {
876             # No, current end tag doesn't equal dirty tag;
877             # Advance to next token
878 27         85 $i++;
879             }
880             }
881             } # _processTokenAsTocEndingToken()
882              
883              
884             #--- HTML::TocGenerator::_processTokenAsTocStartingToken() --------------------
885             # function: Check for token being a ToC-starting-token and process it
886             # accordingly.
887             # args: - $aTokenType: type of token. Can be either TT_TOKENTYPE_START,
888             # _END, _TEXT, _COMMENT or _DECLARATION.
889             # - $aTokenId: token id of currently parsed token
890             # - $aTokenAttributes: reference to hash containing attributes of
891             # currently parsed token
892             # - $aTokenOrig: reference to original token string
893             # returns: 1 if successful, i.e. token is processed as ToC-starting-token, 0
894             # if not.
895              
896             sub _processTokenAsTocStartingToken {
897             # Get arguments
898 924     924   2534 my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aTokenOrig) = @_;
899             # Local variables
900 924         1119 my ($level, $levelToToc, $groupId, $groupToToc);
901 0         0 my ($result, $tocToken, $tagBegin, @tokensTocBegin, $fileSpec);
902             # Bias to token not functioning as ToC-starting-token
903 924         1002 $result = 0;
904             # Loop through start tokens of right type
905 924         983 foreach $tocToken (@{$self->{_tokensTocBegin}[$aTokenType]}) {
  924         2321  
906             # Alias file filter
907 3103         5786 $fileSpec = $tocToken->[TT_GROUP]{'fileSpec'};
908             # File matches?
909 3103 100 66     9672 if (!defined($fileSpec) || (
      66        
910             defined($fileSpec) &&
911             ($self->{_currentFile} =~ m/$fileSpec/)
912             )) {
913             # Yes, file matches;
914             # Alias tag begin
915 3061         5549 $tagBegin = $tocToken->[TT_TAG_BEGIN];
916             # Tag and attributes match?
917 3061 100 66     34972 if (
      100        
      100        
918             defined($tagBegin) &&
919             ($aTokenId =~ m/$tagBegin/) &&
920             HTML::TocGenerator::_doesHashContainHash(
921             $aTokenAttributes, $tocToken->[TT_INCLUDE_ATTRIBUTES_BEGIN], 0
922             ) &&
923             HTML::TocGenerator::_doesHashContainHash(
924             $aTokenAttributes, $tocToken->[TT_EXCLUDE_ATTRIBUTES_BEGIN], 1
925             )
926             ) {
927             # Yes, tag and attributes match;
928             # Aliases
929 254         465 $level = $tocToken->[TT_GROUP]{'level'};
930 254         579 $levelToToc = $tocToken->[TT_TOC]{options}{'levelToToc'};
931 254         430 $groupId = $tocToken->[TT_GROUP]{'groupId'};
932 254         568 $groupToToc = $tocToken->[TT_TOC]{options}{'groupToToc'};
933             # Must level and group be processed?
934 254 100 66     2299 if (
935             ($level =~ m/$levelToToc/) &&
936             ($groupId =~ m/$groupToToc/)
937             ) {
938             # Yes, level and group must be processed;
939             # Indicate token acts as ToC-starting-token
940 236         311 $result = 1;
941             # Start buffering until `_processTokenAsTocEndingToken' returns true
942 236         578 $self->{_holdTocStartToken} = $tocToken;
943 236         428 $self->{_holdBeginTokenType} = $aTokenType;
944 236         307 $self->{_holdBeginTokenAttributes} = $aTokenAttributes;
945 236         484 $self->{_holdBeginTokenOrig} = $$aTokenOrig;
946 236         355 $self->{_holdText} = '';
947 236         322 $self->{_holdTocText} = '';
948 236         314 $self->{_holdChildren} = '';
949 236         304 $self->{_doReleaseElement} = 0;
950              
951             # Must attribute be used as ToC text?
952 236 100       597 if (defined($tocToken->[TT_ATTRIBUTES_TOC])) {
953             # Yes, attribute must be used as ToC text;
954             # # Indicate to not hold element
955             #$self->{_doReleaseElement} = 1;
956             # # Process ToC-starting-token
957             #$self->_processTocStartingToken(
958             # $tocToken, $aTokenType, $aTokenAttributes, $aTokenOrig
959             #);
960             # End attribute
961 5         16 $self->_processTocEndingToken($tocToken);
962             } else {
963             # No, attribute mustn't be used as ToC text;
964             # Add end token to 'end token array'
965 231         965 push(
966 231         280 @{$self->{_tokensTocEnd}[$tocToken->[TT_TAG_TYPE_END]]}, $tocToken
967             );
968             } # if
969             }
970             }
971             }
972             }
973             # Return value
974 924         3143 return $result;
975             } # _processTokenAsTocStartingToken()
976              
977              
978             #--- HTML::TocGenerator::_resetBatchVariables() -------------------------------
979             # function: Reset variables which are set because of batch invocation.
980              
981             sub _resetBatchVariables {
982             # Get arguments
983 218     218   308 my ($self) = @_;
984              
985             # Filename of current file being parsed, empty string if not available
986 218         439 $self->{_currentFile} = "";
987             # Arrays containing start, end, comment, text & declaration tokens which
988             # must trigger the ToC assembling. Each array element may contain a
989             # reference to an array containing the following elements:
990             #
991             # TT_TAG_BEGIN => 0;
992             # TT_TAG_END => 1;
993             # TT_TAG_TYPE_END => 2;
994             # TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
995             # TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
996             # TT_INCLUDE_ATTRIBUTES_END => 5;
997             # TT_EXCLUDE_ATTRIBUTES_END => 6;
998             # TT_GROUP => 7;
999             # TT_TOC => 8;
1000             # TT_ATTRIBUTES_TOC => 9;
1001             #
1002 218         804 $self->{_tokensTocBegin} = [
1003             [], # TT_TOKENTYPE_START
1004             [], # TT_TOKENTYPE_END
1005             [], # TT_TOKENTYPE_COMMENT
1006             [], # TT_TOKENTYPE_TEXT
1007             [] # TT_TOKENTYPE_DECLARATION
1008             ];
1009 218         1484 $self->{_tokensTocEnd} = [
1010             [], # TT_TOKENTYPE_START
1011             [], # TT_TOKENTYPE_END
1012             [], # TT_TOKENTYPE_COMMENT
1013             [], # TT_TOKENTYPE_TEXT
1014             [] # TT_TOKENTYPE_DECLARATION
1015             ];
1016             # TRUE if ToCs have been initialized, FALSE if not.
1017 218         527 $self->{_doneInitializeTocs} = 0;
1018             # Array of ToCs to process
1019 218         485 $self->{_tocs} = [];
1020             # Active anchor name
1021 218         389 $self->{_activeAnchorName} = undef;
1022             # Hold space for toc triggering element
1023             # The element will be processed as soon as the element ends
1024 218         320 $self->{_holdTocStartToken} = undef;
1025 218         301 $self->{_holdBeginTokenType} = undef;
1026 218         307 $self->{_holdBeginTokenAttributes} = undef;
1027 218         582 $self->{_holdBeginTokenOrig} = undef;
1028 218         347 $self->{_holdText} = undef;
1029 218         728 $self->{_holdTocText} = undef;
1030 218         811 $self->{_holdChildren} = undef;
1031             } # _resetBatchVariables()
1032              
1033              
1034             #--- HTML::TocGenerator::_resetStackVariables() -------------------------------
1035             # function: Reset variables which cumulate during ToC generation.
1036              
1037             sub _resetStackVariables {
1038             # Get arguments
1039 4     4   8 my ($self) = @_;
1040             # Reset variables
1041 4         18 $self->{levels} = undef;
1042 4         10 $self->{groupIdLevels} = undef;
1043             } # _resetStackVariables()
1044              
1045              
1046             #--- HTML::TocGenerator::_setActiveAnchorName() -------------------------------
1047             # function: Set active anchor name.
1048             # args: - aAnchorName: Name of anchor name to set active.
1049              
1050             sub _setActiveAnchorName {
1051             # Get arguments
1052 0     0   0 my ($self, $aAnchorName) = @_;
1053             # Set active anchor name
1054 0         0 $self->{_activeAnchorName} = $aAnchorName;
1055             } # _setActiveAnchorName()
1056              
1057              
1058             #--- HTML::TocGenerator::_showWarning() ---------------------------------------
1059             # function: Show warning.
1060             # args: - aWarningNr: Number of warning to show.
1061             # - aWarningArgs: Arguments to display within the warning.
1062              
1063             sub _showWarning {
1064             # Get arguments
1065 0     0   0 my ($self, $aWarningNr, $aWarningArgs) = @_;
1066             # Local variables
1067 0         0 my (%warnings);
1068             # Set warnings
1069 0         0 %warnings = (
1070             WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS() =>
1071             "ToC attribute '%s' not available within token '%s'.",
1072             );
1073             # Show warning
1074 0         0 print STDERR "warning ($aWarningNr): " . sprintf($warnings{"$aWarningNr"}, @$aWarningArgs) . "\n";
1075             } # _showWarning()
1076              
1077              
1078             #--- HTML::TocGenerator::afterAnchorNameBegin() ------------------------
1079             # function: After anchor name begin processing method. Leave it up to the
1080             # descendant to do something useful with it.
1081             # args: - $aAnchorName
1082             # - $aToc: Reference to ToC to which anchorname belongs.
1083              
1084 33     33 0 50 sub afterAnchorNameBegin {
1085             } # anchorNameBegin()
1086              
1087              
1088             #--- HTML::TocGenerator::anchorId() -------------------------------------------
1089             # function: Anchor id processing method. Leave it up to the descendant to do
1090             # something useful with it.
1091             # args: - $aAnchorId
1092             # - $aToc: Reference to ToC to which anchorId belongs.
1093              
1094 0     0 0 0 sub anchorId {
1095             } # anchorId()
1096              
1097              
1098             #--- HTML::TocGenerator::anchorNameBegin() ------------------------------------
1099             # function: Anchor name begin processing method. Leave it up to the descendant
1100             # to do something useful with it.
1101             # args: - $aAnchorName
1102             # - $aToc: Reference to ToC to which anchorname belongs.
1103              
1104             sub anchorNameBegin {
1105             # Get arguments
1106 206     206 0 383 my ($self, $aAnchorName, $aToc) = @_;
1107 206         792 return $aAnchorName;
1108             } # anchorNameBegin()
1109              
1110              
1111             #--- HTML::TocGenerator::anchorNameEnd() --------------------------------------
1112             # function: Anchor name end processing method. Leave it up to the descendant
1113             # to do something useful with it.
1114             # args: - $aAnchorName
1115             # - $aToc: Reference to ToC to which anchorname belongs.
1116              
1117 0     0 0 0 sub anchorNameEnd {
1118             } # anchorNameEnd()
1119              
1120              
1121             #--- HTML::TocGenerator::comment() --------------------------------------------
1122             # function: Process comment.
1123             # args: - $aComment: comment text with '' tags stripped off.
1124              
1125             sub comment {
1126             # Get arguments
1127 17     17 1 97 my ($self, $aComment) = @_;
1128             # Bias to token not functioning as ToC-starting-token
1129 17         31 $self->{_isTocToken} = 0;
1130             # Must a ToC be generated?
1131 17 50       49 if ($self->{_doGenerateToc}) {
1132             # Yes, a ToC must be generated;
1133             # Process comment as ToC-starting-token
1134             # Is comment a ToC-starting-token?
1135 17 50       45 if (! ($self->{_isTocToken} = $self->_processTokenAsTocStartingToken(
1136             TT_TOKENTYPE_COMMENT, $aComment, undef, \$aComment
1137             ))) {
1138             # No, comment isn't a ToC starting token;
1139 17         69 $self->_processTocTokenChildren('');
1140             } # if
1141             # Process end tag as token which ends ToC registration
1142             $self->_processTokenAsTocEndingToken(
1143 17         48 TT_TOKENTYPE_COMMENT, $aComment
1144             );
1145             }
1146             } # comment()
1147              
1148              
1149             #--- HTML::TocGenerator::declaration() -----------------------------------------
1150             # function: This function is called every time a declaration is encountered
1151             # by HTML::Parser.
1152              
1153             sub declaration {
1154             # Get arguments
1155 4     4 1 11 my ($self, $aDeclaration) = @_;
1156             # Bias to token not functioning as ToC-starting-token
1157 4         10 $self->{_isTocToken} = 0;
1158             # Must a ToC be generated?
1159 4 50       19 if ($self->{_doGenerateToc}) {
1160             # Yes, a ToC must be generated
1161             # Process declaration as ToC-starting-token
1162             # Is declaration a ToC-starting-token?
1163 4 50       32 if (! ($self->{_isTocToken} = $self->_processTokenAsTocStartingToken(
1164             TT_TOKENTYPE_DECLARATION, $aDeclaration, undef, \$aDeclaration
1165             ))) {
1166             # No, declaration isn't a ToC-starting-token
1167 4         33 $self->_processTocTokenChildren('');
1168             } # if
1169             # Process end tag as token which ends ToC registration
1170             $self->_processTokenAsTocEndingToken(
1171 4         28 TT_TOKENTYPE_DECLARATION, $aDeclaration
1172             );
1173             }
1174             } # declaration()
1175              
1176              
1177             #--- HTML::TocGenerator::end() ------------------------------------------------
1178             # function: This function is called every time a closing tag is encountered.
1179             # args: - $aTag: tag name (in lower case).
1180             # - $aOrigText: tag name including brackets.
1181              
1182             sub end {
1183             # Get arguments
1184 440     440 1 760 my ($self, $aTag, $aOrigText) = @_;
1185             # Local variables
1186 440         502 my ($tag, $toc, $i);
1187             # Must a ToC be generated?
1188 440 100       1186 if ($self->{_doGenerateToc}) {
1189             # Yes, a ToC must be generated
1190             # Process end tag as ToC-starting-token
1191 435         1251 $self->{_isTocToken} = $self->_processTokenAsTocStartingToken(
1192             TT_TOKENTYPE_END, $aTag, undef, \$aOrigText
1193             );
1194             # Process end tag as ToC-ending-token
1195 435         1292 $self->_processTokenAsTocEndingToken(
1196             TT_TOKENTYPE_END, $aTag
1197             );
1198             # Tag is of type 'anchor'?
1199 435 50 33     1450 if (defined($self->{_activeAnchorName}) && ($aTag eq "a")) {
1200             # Yes, tag is of type 'anchor';
1201             # Reset dirty anchor
1202 0         0 $self->{_activeAnchorName} = undef;
1203             }
1204 435 50       1040 if (! $self->{_isTocToken}) {
1205 435         1431 $self->_processTocTokenChildren($aOrigText);
1206             } # if
1207             }
1208             } # end()
1209              
1210              
1211             #--- HTML::TocGenerator::extend() ---------------------------------------------
1212             # function: Extend ToCs.
1213             # args: - $aTocs: Reference to array of ToC objects
1214             # - $aString: String to parse.
1215              
1216             sub extend {
1217             # Get arguments
1218 2     2 0 9 my ($self, $aTocs, $aString) = @_;
1219             # Initialize TocGenerator batch
1220 2         6 $self->_initializeExtenderBatch($aTocs);
1221             # Extend ToCs
1222 2         8 $self->_extend($aString);
1223             # Deinitialize TocGenerator batch
1224 2         6 $self->_deinitializeExtenderBatch();
1225             } # extend()
1226              
1227              
1228             #--- HTML::TocGenerator::extendFromFile() -------------------------------------
1229             # function: Extend ToCs.
1230             # args: - @aTocs: Reference to array of ToC objects
1231             # - @aFiles: Reference to array of files to parse.
1232              
1233             sub extendFromFile {
1234             # Get arguments
1235 4     4 0 980 my ($self, $aTocs, $aFiles) = @_;
1236             # Initialize TocGenerator batch
1237 4         17 $self->_initializeExtenderBatch($aTocs);
1238             # Extend ToCs
1239 4         16 $self->_extendFromFile($aFiles);
1240             # Deinitialize TocGenerator batch
1241 4         14 $self->_deinitializeExtenderBatch();
1242             } # extendFromFile()
1243              
1244              
1245             #--- HTML::TocGenerator::generate() -------------------------------------------
1246             # function: Generate ToC.
1247             # args: - $aToc: Reference to (array of) ToC object(s)
1248             # - $aString: Reference to string to parse
1249             # - $aOptions: optional options
1250              
1251             sub generate {
1252             # Get arguments
1253 20     20 0 948 my ($self, $aToc, $aString, $aOptions) = @_;
1254             # Initialize TocGenerator batch
1255 20         75 $self->_initializeGeneratorBatch($aToc, $aOptions);
1256             # Do generate ToC
1257 20         73 $self->_generate($aString);
1258             # Deinitialize TocGenerator batch
1259 20         63 $self->_deinitializeGeneratorBatch();
1260             } # generate()
1261              
1262              
1263             #--- HTML::TocGenerator::generateFromFile() -----------------------------------
1264             # function: Generate ToC.
1265             # args: - $aToc: Reference to (array of) ToC object(s)
1266             # - $aFile: (reference to array of) file to parse.
1267             # - $aOptions: optional options
1268              
1269             sub generateFromFile {
1270             # Get arguments
1271 17     17 0 106 my ($self, $aToc, $aFile, $aOptions) = @_;
1272             # Initialize TocGenerator batch
1273 17         55 $self->_initializeGeneratorBatch($aToc, $aOptions);
1274             # Do generate ToC
1275 17         50 $self->_generateFromFile($aFile);
1276             # Deinitialize TocGenerator batch
1277 17         52 $self->_deinitializeGeneratorBatch();
1278             } # generateFromFile()
1279              
1280              
1281             #--- HTML::TocGenerator::formatNumber() --------------------------------
1282             # function: Heading number formatting method. Leave it up to the descendant
1283             # to do something useful with it.
1284             # args: - $aNumber
1285             # - $aToc: Reference to ToC to which anchorname belongs.
1286              
1287             sub formatNumber {
1288             # Get arguments
1289 88     88 0 293 my ($self, $aNumber, $aToc) = @_;
1290 88         390 return $aNumber;
1291             } # number()
1292              
1293              
1294             #--- HTML::TocGenerator::number() ---------------------------------------------
1295             # function: Heading number processing method. Leave it up to the descendant
1296             # to do something useful with it.
1297             # args: - $aNumber
1298             # - $aToc: Reference to ToC to which anchorname belongs.
1299              
1300             sub number {
1301             # Get arguments
1302 0     0 0 0 my ($self, $aNumber, $aToc) = @_;
1303             } # number()
1304              
1305              
1306             #--- HTML::TocGenerator::parse() ----------------------------------------------
1307             # function: Parse scalar.
1308             # args: - $aString: string to parse
1309              
1310             sub parse {
1311             # Get arguments
1312 133     133 1 3863 my ($self, $aString) = @_;
1313             # Call ancestor
1314 133         1233 $self->SUPER::parse($aString);
1315             } # parse()
1316              
1317              
1318             #--- HTML::TocGenerator::parse_file() -----------------------------------------
1319             # function: Parse file.
1320              
1321             sub parse_file {
1322             # Get arguments
1323 43     43 1 77 my ($self, $aFile) = @_;
1324             # Call ancestor
1325 43         196 $self->SUPER::parse_file($aFile);
1326             } # parse_file()
1327              
1328              
1329             #--- HTML::TocGenerator::setOptions() -----------------------------------------
1330             # function: Set options.
1331             # args: - aOptions: Reference to hash containing options.
1332              
1333             sub setOptions {
1334             # Get arguments
1335 145     145 0 215 my ($self, $aOptions) = @_;
1336             # Options are defined?
1337 145 100       426 if (defined($aOptions)) {
1338             # Yes, options are defined; add to options
1339 58         105 %{$self->{options}} = (%{$self->{options}}, %$aOptions);
  58         294  
  58         222  
1340             }
1341             } # setOptions()
1342              
1343              
1344             #--- HTML::TocGenerator::start() ----------------------------------------------
1345             # function: This function is called every time an opening tag is encountered.
1346             # args: - $aTag: tag name (in lower case).
1347             # - $aAttr: reference to hash containing all tag attributes (in lower
1348             # case).
1349             # - $aAttrSeq: reference to array containing all tag attributes (in
1350             # lower case) in the original order
1351             # - $aTokenOrig: the original token string
1352              
1353             sub start {
1354             # Get arguments
1355 473     473 1 777 my ($self, $aTag, $aAttr, $aAttrSeq, $aTokenOrig) = @_;
1356             # Bias to token not functioning as ToC-starting-token
1357 473         978 $self->{_isTocToken} = 0;
1358             # Must a ToC be generated?
1359 473 100       1149 if ($self->{_doGenerateToc}) {
1360             # Yes, a ToC must be generated
1361             # Process start tag as ToC token
1362             # Is start tag a ToC token?
1363 468 100       1189 if (! ($self->{_isTocToken} = $self->_processTokenAsTocStartingToken(
1364             TT_TOKENTYPE_START, $aTag, $aAttr, \$aTokenOrig
1365             ))) {
1366             # No, start tag isn't ToC token
1367 232         823 $self->_processTocTokenChildren($aTokenOrig);
1368             }
1369              
1370             # Process end tag as ToC-ending-token
1371             $self->_processTokenAsTocEndingToken(
1372 468         1232 TT_TOKENTYPE_START, $aTag
1373             );
1374             }
1375              
1376             } # start()
1377              
1378              
1379             #--- HTML::TocGenerator::text() -----------------------------------------------
1380             # function: This function is called every time plain text is encountered.
1381             # args: - @_: array containing data.
1382              
1383             sub text {
1384             # Get arguments
1385 843     843 1 3058 my ($self, $aText) = @_;
1386             # Local variables
1387 843         889 my ($text, $toc, $i, $token, $tokens);
1388             # Must a ToC be generated?
1389 843 100       2319 if ($self->{_doGenerateToc}) {
1390             # Yes, a ToC must be generated
1391             # Are there dirty start tags?
1392              
1393             # Loop through token types
1394 838         878 foreach $tokens (@{$self->{_tokensTocEnd}}) {
  838         1806  
1395             # Loop though tokens
1396 4190         8777 foreach $token (@$tokens) {
1397             # Add text to toc
1398              
1399             # Alias
1400 257         355 $toc = $token->[TT_TOC];
1401             # Add text to ToC
1402 257         722 $self->_processTocText($aText, $toc);
1403             # Process text inside token
1404 257         1338 $self->_processTocTokenText($aText, $toc);
1405             }
1406             }
1407             }
1408             } # text()
1409              
1410              
1411              
1412              
1413             #=== HTML::_TokenTocParser ====================================================
1414             # function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1415             # inserted into the ToC.
1416             # note: Used internally.
1417              
1418             package HTML::_TokenTocParser;
1419              
1420              
1421             BEGIN {
1422 12     12   157 use vars qw(@ISA);
  12         36  
  12         827  
1423              
1424 12     12   3591 @ISA = qw(HTML::Parser);
1425             }
1426              
1427              
1428 12     12   56 END {}
1429              
1430              
1431             #--- HTML::_TokenTocParser::new() ---------------------------------------------
1432             # function: Constructor
1433              
1434             sub new {
1435             # Get arguments
1436 245     245   405 my ($aType) = @_;
1437             # Create instance
1438 245         874 my $self = $aType->SUPER::new;
1439              
1440             # Return instance
1441 245         12347 return $self;
1442             } # new()
1443              
1444              
1445             #--- HTML::_TokenTocParser::_parseAttributes() --------------------------------
1446             # function: Parse attributes.
1447             # args: - $aAttr: Reference to hash containing all tag attributes (in lower
1448             # case).
1449             # - $aIncludeAttributes: Reference to hash to which 'include
1450             # attributes' must be added.
1451             # - $aExcludeAttributes: Reference to hash to which 'exclude
1452             # attributes' must be added.
1453             # - $aTocAttributes: Reference to hash to which 'ToC attributes'
1454             # must be added.
1455              
1456             sub _parseAttributes {
1457             # Get arguments
1458             my (
1459 517     517   812 $self, $aAttr, $aIncludeAttributes, $aExcludeAttributes,
1460             $aTocAttributes
1461             ) = @_;
1462             # Local variables
1463 517         783 my ($key, $value);
1464 0         0 my ($attributeToExcludeToken, $attributeToTocToken);
1465             # Get token which marks attributes which must be excluded
1466 517         1073 $attributeToExcludeToken = $self->{_toc}{options}{'attributeToExcludeToken'};
1467 517         843 $attributeToTocToken = $self->{_toc}{options}{'attributeToTocToken'};
1468             # Loop through attributes
1469 517         2112 while (($key, $value) = each %$aAttr) {
1470             # Attribute value equals 'ToC token'?
1471 38 100       207 if ($value =~ m/$attributeToTocToken/) {
1472             # Yes, attribute value equals 'ToC token';
1473             # Add attribute to 'ToC attributes'
1474 3         18 push @$aTocAttributes, $key;
1475             }
1476             else {
1477             # No, attribute isn't 'ToC' token;
1478             # Attribute value starts with 'exclude token'?
1479 35 100       220 if ($value =~ m/^$attributeToExcludeToken(.*)/) {
1480             # Yes, attribute value starts with 'exclude token';
1481             # Add attribute to 'exclude attributes'
1482 11         81 $$aExcludeAttributes{$key} = "$1";
1483             }
1484             else {
1485             # No, attribute key doesn't start with '-';
1486             # Add attribute to 'include attributes'
1487 24         127 $$aIncludeAttributes{$key} = $value;
1488             }
1489             }
1490             }
1491             } # _parseAttributes()
1492              
1493              
1494              
1495              
1496             #=== HTML::_TokenTocBeginParser ===============================================
1497             # function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1498             # inserted into the ToC.
1499             # note: Used internally.
1500              
1501             package HTML::_TokenTocBeginParser;
1502              
1503              
1504             BEGIN {
1505 12     12   80 use vars qw(@ISA);
  12         27  
  12         483  
1506              
1507 12     12   11209 @ISA = qw(HTML::_TokenTocParser);
1508             }
1509              
1510 12     12   52 END {}
1511              
1512              
1513             #--- HTML::_TokenTocBeginParser::new() ----------------------------------------
1514             # function: Constructor
1515              
1516             sub new {
1517             # Get arguments
1518 94     94   162 my ($aType, $aTokenArray) = @_;
1519             # Create instance
1520 94         1202 my $self = $aType->SUPER::new;
1521             # Reference token array
1522 94         365 $self->{tokens} = $aTokenArray;
1523             # Reference to last added token
1524 94         215 $self->{_lastAddedToken} = undef;
1525 94         234 $self->{_lastAddedTokenType} = undef;
1526             # Return instance
1527 94         192 return $self;
1528             } # new()
1529              
1530              
1531             #--- HTML::_TokenTocBeginParser::_processAttributes() -------------------------
1532             # function: Process attributes.
1533             # args: - $aAttributes: Attributes to parse.
1534              
1535             sub _processAttributes {
1536             # Get arguments
1537 478     478   609 my ($self, $aAttributes) = @_;
1538             # Local variables
1539 478         742 my (%includeAttributes, %excludeAttributes, @tocAttributes);
1540              
1541             # Parse attributes
1542 478         1195 $self->_parseAttributes(
1543             $aAttributes, \%includeAttributes, \%excludeAttributes, \@tocAttributes
1544             );
1545             # Include attributes are specified?
1546 478 100       1279 if (keys(%includeAttributes) > 0) {
1547             # Yes, include attributes are specified;
1548             # Store include attributes
1549 24         44 @${$self->{_lastAddedToken}}[
  24         153  
1550             HTML::TocGenerator::TT_INCLUDE_ATTRIBUTES_BEGIN
1551             ] = \%includeAttributes;
1552             }
1553             # Exclude attributes are specified?
1554 478 100       1147 if (keys(%excludeAttributes) > 0) {
1555             # Yes, exclude attributes are specified;
1556             # Store exclude attributes
1557 11         23 @${$self->{_lastAddedToken}}[
  11         29  
1558             HTML::TocGenerator::TT_EXCLUDE_ATTRIBUTES_BEGIN
1559             ] = \%excludeAttributes;
1560             }
1561             # Toc attributes are specified?
1562 478 100       2852 if (@tocAttributes > 0) {
1563             # Yes, toc attributes are specified;
1564             # Store toc attributes
1565 3         6 @${$self->{_lastAddedToken}}[
  3         23  
1566             HTML::TocGenerator::TT_ATTRIBUTES_TOC
1567             ] = \@tocAttributes;
1568             }
1569             } # _processAttributes()
1570              
1571              
1572             #--- HTML::_TokenTocBeginParser::_processToken() ------------------------------
1573             # function: Process token.
1574             # args: - $aTokenType: Type of token to process.
1575             # - $aTag: Tag of token.
1576              
1577             sub _processToken {
1578             # Get arguments
1579 478     478   673 my ($self, $aTokenType, $aTag) = @_;
1580             # Local variables
1581 478         492 my ($tokenArray, $index);
1582             # Push element on array of update tokens
1583 478         526 $index = push(@{$self->{tokens}[$aTokenType]}, []) - 1;
  478         1346  
1584             # Alias token array to add element to
1585 478         785 $tokenArray = $self->{tokens}[$aTokenType];
1586             # Indicate last updated token array element
1587 478         604 $self->{_lastAddedTokenType} = $aTokenType;
1588 478         947 $self->{_lastAddedToken} = \$$tokenArray[$index];
1589             # Add fields
1590 478         1021 $$tokenArray[$index][HTML::TocGenerator::TT_TAG_BEGIN] = $aTag;
1591 478         1054 $$tokenArray[$index][HTML::TocGenerator::TT_GROUP] = $self->{_group};
1592 478         1097 $$tokenArray[$index][HTML::TocGenerator::TT_TOC] = $self->{_toc};
1593             } # _processToken()
1594              
1595              
1596             #--- HTML::_TokenTocBeginParser::comment() ------------------------------------
1597             # function: Process comment.
1598             # args: - $aComment: comment text with '' tags stripped off.
1599              
1600             sub comment {
1601             # Get arguments
1602 0     0   0 my ($self, $aComment) = @_;
1603             # Process token
1604 0         0 $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment);
1605             } # comment()
1606              
1607              
1608             #--- HTML::_TokenTocBeginParser::declaration() --------------------------------
1609             # function: This function is called every time a markup declaration is
1610             # encountered by HTML::Parser.
1611             # args: - $aDeclaration: Markup declaration.
1612              
1613             sub declaration {
1614             # Get arguments
1615 0     0   0 my ($self, $aDeclaration) = @_;
1616             # Process token
1617 0         0 $self->_processToken(
1618             HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration
1619             );
1620             } # declaration()
1621              
1622            
1623             #--- HTML::_TokenTocBeginParser::end() ----------------------------------------
1624             # function: This function is called every time a closing tag is encountered
1625             # by HTML::Parser.
1626             # args: - $aTag: tag name (in lower case).
1627              
1628             sub end {
1629             # Get arguments
1630 0     0   0 my ($self, $aTag, $aTokenOrig) = @_;
1631             # Process token
1632 0         0 $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag);
1633             } # end()
1634              
1635              
1636             #--- HTML::_TokenTocBeginParser::parse() --------------------------------------
1637             # function: Parse begin token.
1638             # args: - $aToken: 'toc token' to parse
1639              
1640             sub parse {
1641             # Get arguments
1642 478     478   649 my ($self, $aString) = @_;
1643             # Call ancestor
1644 478         4167 $self->SUPER::parse($aString);
1645             } # parse()
1646              
1647              
1648             #--- HTML::_TokenTocBeginParser->setGroup() -----------------------------------
1649             # function: Set current 'tokenToToc' group.
1650              
1651             sub setGroup {
1652             # Get arguments
1653 478     478   671 my ($self, $aGroup) = @_;
1654             # Set current 'tokenToToc' group
1655 478         897 $self->{_group} = $aGroup;
1656             } # setGroup()
1657              
1658              
1659             #--- HTML::_TokenTocBeginParser->setToc() -------------------------------------
1660             # function: Set current ToC.
1661              
1662             sub setToc {
1663             # Get arguments
1664 103     103   157 my ($self, $aToc) = @_;
1665             # Set current ToC
1666 103         239 $self->{_toc} = $aToc;
1667             } # setToc()
1668              
1669              
1670             #--- HTML::_TokenTocBeginParser::start() --------------------------------------
1671             # function: This function is called every time an opening tag is encountered.
1672             # args: - $aTag: tag name (in lower case).
1673             # - $aAttr: reference to hash containing all tag attributes (in lower
1674             # case).
1675             # - $aAttrSeq: reference to array containing all attribute keys (in
1676             # lower case) in the original order
1677             # - $aOrigText: the original HTML text
1678              
1679             sub start {
1680             # Get arguments
1681 478     478   959 my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1682             # Process token
1683 478         1030 $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag);
1684             # Process attributes
1685 478         989 $self->_processAttributes($aAttr);
1686             } # start()
1687              
1688              
1689             #--- HTML::_TokenTocBeginParser::text() ---------------------------------------
1690             # function: This function is called every time plain text is encountered.
1691             # args: - @_: array containing data.
1692              
1693             sub text {
1694             # Get arguments
1695 0     0   0 my ($self, $aText) = @_;
1696             # Was token already created and is last added token of type 'text'?
1697 0 0 0     0 if (
1698             defined($self->{_lastAddedToken}) &&
1699             $self->{_lastAddedTokenType} == HTML::TocGenerator::TT_TOKENTYPE_TEXT
1700             ) {
1701             # Yes, token is already created;
1702             # Add tag to existing token
1703 0         0 @${$self->{_lastAddedToken}}[HTML::TocGenerator::TT_TAG_BEGIN] .= $aText;
  0         0  
1704             }
1705             else {
1706             # No, token isn't created;
1707             # Process token
1708 0         0 $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
1709             }
1710             } # text()
1711              
1712              
1713              
1714              
1715             #=== HTML::_TokenTocEndParser =================================================
1716             # function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1717             # inserted into the ToC.
1718             # note: Used internally.
1719              
1720             package HTML::_TokenTocEndParser;
1721              
1722              
1723             BEGIN {
1724 12     12   92 use vars qw(@ISA);
  12         28  
  12         548  
1725              
1726 12     12   10100 @ISA = qw(HTML::_TokenTocParser);
1727             }
1728              
1729              
1730 12     12   992 END {}
1731              
1732              
1733             #--- HTML::_TokenTocEndParser::new() ------------------------------------------
1734             # function: Constructor
1735             # args: - $aType: Class type.
1736              
1737             sub new {
1738             # Get arguments
1739 94     94   175 my ($aType) = @_;
1740             # Create instance
1741 94         305 my $self = $aType->SUPER::new;
1742             # Reference to last added token
1743 94         278 $self->{_lastAddedToken} = undef;
1744             # Return instance
1745 94         200 return $self;
1746             } # new()
1747              
1748              
1749             #--- HTML::_TokenTocEndParser::_processAttributes() ---------------------------
1750             # function: Process attributes.
1751             # args: - $aAttributes: Attributes to parse.
1752              
1753             sub _processAttributes {
1754             # Get arguments
1755 0     0   0 my ($self, $aAttributes) = @_;
1756             # Local variables
1757 0         0 my (%includeAttributes, %excludeAttributes);
1758              
1759             # Parse attributes
1760 0         0 $self->_parseAttributes(
1761             $aAttributes, \%includeAttributes, \%excludeAttributes
1762             );
1763             # Include attributes are specified?
1764 0 0       0 if (keys(%includeAttributes) > 0) {
1765             # Yes, include attributes are specified;
1766             # Store include attributes
1767 0         0 @${$self->{_Token}}[
  0         0  
1768             HTML::TocGenerator::TT_INCLUDE_ATTRIBUTES_END
1769             ] = \%includeAttributes;
1770             }
1771             # Exclude attributes are specified?
1772 0 0       0 if (keys(%excludeAttributes) > 0) {
1773             # Yes, exclude attributes are specified;
1774             # Store exclude attributes
1775 0         0 @${$self->{_Token}}[
  0         0  
1776             HTML::TocGenerator::TT_EXCLUDE_ATTRIBUTES_END
1777             ] = \%excludeAttributes;
1778             }
1779             } # _processAttributes()
1780              
1781              
1782             #--- HTML::_TokenTocEndParser::_processToken() --------------------------------
1783             # function: Process token.
1784             # args: - $aTokenType: Type of token to process.
1785             # - $aTag: Tag of token.
1786              
1787             sub _processToken {
1788             # Get arguments
1789 478     478   814 my ($self, $aTokenType, $aTag) = @_;
1790             # Update token
1791 478         661 @${$self->{_token}}[HTML::TocGenerator::TT_TAG_TYPE_END] = $aTokenType;
  478         917  
1792 478         653 @${$self->{_token}}[HTML::TocGenerator::TT_TAG_END] = $aTag;
  478         986  
1793             # Indicate token type which has been processed
1794 478         1170 $self->{_lastAddedTokenType} = $aTokenType;
1795             } # _processToken()
1796              
1797              
1798             #--- HTML::_TokenTocEndParser::comment() --------------------------------------
1799             # function: Process comment.
1800             # args: - $aComment: comment text with '' tags stripped off.
1801              
1802             sub comment {
1803             # Get arguments
1804 0     0   0 my ($self, $aComment) = @_;
1805             # Process token
1806 0         0 $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment);
1807             } # comment()
1808              
1809              
1810             #--- HTML::_TokenTocEndParser::declaration() -------------------------
1811             # function: This function is called every time a markup declaration is
1812             # encountered by HTML::Parser.
1813             # args: - $aDeclaration: Markup declaration.
1814              
1815             sub declaration {
1816             # Get arguments
1817 0     0   0 my ($self, $aDeclaration) = @_;
1818             # Process token
1819 0         0 $self->_processToken(
1820             HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration
1821             );
1822             } # declaration()
1823              
1824            
1825             #--- HTML::_TokenTocEndParser::end() ------------------------------------------
1826             # function: This function is called every time a closing tag is encountered
1827             # by HTML::Parser.
1828             # args: - $aTag: tag name (in lower case).
1829              
1830             sub end {
1831             # Get arguments
1832 3     3   6 my ($self, $aTag, $aOrigText) = @_;
1833             # Process token
1834 3         10 $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag);
1835             } # end()
1836              
1837              
1838             #--- HTML::_TokenTocEndParser::parse() ----------------------------------------
1839             # function: Parse token.
1840             # args: - $aString: 'toc token' to parse
1841             # - $aToken: Reference to token
1842             # - $aTokenTypeBegin: Type of begin token
1843              
1844             sub parse {
1845             # Get arguments
1846 478     478   1061 my ($self, $aString, $aToken, $aTokenTypeBegin) = @_;
1847             # Token argument specified?
1848 478 50       1005 if (defined($aToken)) {
1849             # Yes, token argument is specified;
1850             # Store token reference
1851 478         772 $self->{_token} = $aToken;
1852             }
1853             # End tag defined?
1854 478 100       889 if (! defined($aString)) {
1855             # No, end tag isn't defined;
1856             # Last added tokentype was of type 'start'?
1857 475 50 33     2141 if (
1858             (defined($aTokenTypeBegin)) &&
1859             ($aTokenTypeBegin == HTML::TocGenerator::TT_TOKENTYPE_START)
1860             ) {
1861             # Yes, last added tokentype was of type 'start';
1862             # Assume end tag
1863 475         1370 $self->_processToken(
1864             HTML::TocGenerator::TT_TAG_END,
1865 475         616 @${$self->{_token}}[HTML::TocGenerator::TT_TAG_BEGIN]
1866             );
1867             }
1868             }
1869             else {
1870             # Call ancestor
1871 3         23 $self->SUPER::parse($aString);
1872             }
1873             } # parse()
1874              
1875              
1876             #--- HTML::_TokenTocEndParser::start() ----------------------------------------
1877             # function: This function is called every time an opening tag is encountered.
1878             # args: - $aTag: tag name (in lower case).
1879             # - $aAttr: reference to hash containing all tag attributes (in lower
1880             # case).
1881             # - $aAttrSeq: reference to array containing all attribute keys (in
1882             # lower case) in the original order
1883             # - $aOrigText: the original HTML text
1884              
1885             sub start {
1886             # Get arguments
1887 0     0     my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1888             # Process token
1889 0           $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag);
1890             # Process attributes
1891 0           $self->_processAttributes($aAttr);
1892             } # start()
1893              
1894              
1895             #--- HTML::_TokenTocEndParser::text() -----------------------------------------
1896             # function: This function is called every time plain text is encountered.
1897             # args: - @_: array containing data.
1898              
1899             sub text {
1900             # Get arguments
1901 0     0     my ($self, $aText) = @_;
1902              
1903             # Is token already created?
1904 0 0         if (defined($self->{_lastAddedTokenType})) {
1905             # Yes, token is already created;
1906             # Add tag to existing token
1907 0           @${$self->{_token}}[HTML::TocGenerator::TT_TAG_END] .= $aText;
  0            
1908             }
1909             else {
1910             # No, token isn't created;
1911             # Process token
1912 0           $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
1913             }
1914             } # text()
1915              
1916              
1917              
1918              
1919             #=== HTML::_AnchorNameAssembler =============================================
1920             # function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1921             # inserted into the ToC.
1922             # note: Used internally.
1923              
1924             package HTML::_AnchorNameAssembler;
1925              
1926              
1927             #--- HTML::_AnchorNameAssembler::new() ---------------------------------
1928             # function: Constructor
1929             # args: - $aType: Class type.
1930              
1931             sub new {
1932 0     0     my $class = shift;
1933 0           my $self = {};
1934 0           bless ($self, $class);
1935             # Return instance
1936 0           return $self;
1937             } # new()
1938              
1939              
1940             1;