1 #=== HTML::TocGenerator =======================================================
2 # function: Generate 'HTML::Toc' table of contents.
3 # note: - 'TT' is an abbrevation of 'TocToken'.
6 package HTML
::TocGenerator
;
14 use vars
qw(@ISA $VERSION);
18 @ISA = qw(HTML::Parser);
23 use constant WARNING_NESTED_ANCHOR_PS_WITHIN_PS
=> 1;
24 use constant WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS
=> 2;
27 use constant TOC_TOKEN_ID
=> 0;
28 use constant TOC_TOKEN_INCLUDE
=> 1;
29 use constant TOC_TOKEN_EXCLUDE
=> 2;
30 use constant TOC_TOKEN_TOKENS
=> 3;
31 use constant TOC_TOKEN_GROUP
=> 4;
32 use constant TOC_TOKEN_TOC
=> 5;
35 use constant TT_TAG_BEGIN
=> 0;
36 use constant TT_TAG_END
=> 1;
37 use constant TT_TAG_TYPE_END
=> 2;
38 use constant TT_INCLUDE_ATTRIBUTES_BEGIN
=> 3;
39 use constant TT_EXCLUDE_ATTRIBUTES_BEGIN
=> 4;
40 use constant TT_INCLUDE_ATTRIBUTES_END
=> 5;
41 use constant TT_EXCLUDE_ATTRIBUTES_END
=> 6;
42 use constant TT_GROUP
=> 7;
43 use constant TT_TOC
=> 8;
44 use constant TT_ATTRIBUTES_TOC
=> 9;
47 use constant CONTAINMENT_INCLUDE
=> 0;
48 use constant CONTAINMENT_EXCLUDE
=> 1;
50 use constant TEMPLATE_ANCHOR
=> '$groupId."-".$node';
51 use constant TEMPLATE_ANCHOR_HREF
=>
52 '"<a href=#".' . TEMPLATE_ANCHOR
. '.">"';
53 use constant TEMPLATE_ANCHOR_HREF_FILE
=>
54 '"<a href=".$file."#".' . TEMPLATE_ANCHOR
. '.">"';
55 use constant TEMPLATE_ANCHOR_NAME
=>
56 '"<a name=".' . TEMPLATE_ANCHOR
. '.">"';
58 use constant TEMPLATE_TOKEN_NUMBER
=> '"$node  "';
61 use constant TT_TOKENTYPE_START
=> 0;
62 use constant TT_TOKENTYPE_END
=> 1;
63 use constant TT_TOKENTYPE_TEXT
=> 2;
64 use constant TT_TOKENTYPE_COMMENT
=> 3;
65 use constant TT_TOKENTYPE_DECLARATION
=> 4;
71 #--- HTML::TocGenerator::new() ------------------------------------------------
72 # function: Constructor
77 my $self = $aType->SUPER::new
;
78 # Bias to not generate ToC
79 $self->{_doGenerateToc
} = 0;
80 # Bias to not use global groups
81 $self->{_doUseGroupsGlobal
} = 0;
84 # Reset internal variables
85 $self->_resetBatchVariables();
87 $self->{options
} = {};
93 #--- HTML::TocGenerator::_deinitializeBatch() ---------------------------------
95 sub _deinitializeBatch
() {
98 } # _deinitializeBatch()
101 #--- HTML::TocGenerator::_deinitializeExtenderBatch() -------------------------
103 sub _deinitializeExtenderBatch
() {
106 # Do general batch deinitialization
107 $self->_deinitializeBatch();
108 # Indicate end of ToC generation
109 $self->{_doGenerateToc
} = 0;
110 # Reset batch variables
111 $self->_resetBatchVariables();
112 } # _deinitializeExtenderBatch()
115 #--- HTML::TocGenerator::_deinitializeGeneratorBatch() ------------------------
117 sub _deinitializeGeneratorBatch
() {
120 # Do 'extender' batch deinitialization
121 $self->_deinitializeExtenderBatch();
122 } # _deinitializeBatchGenerator()
125 #--- HTML::TocGenerator::_doesHashContainHash() -------------------------------
126 # function: Determines whether hash1 matches regular expressions of hash2.
129 # - $aContainmentType: 0 (include) or 1 (exclude)
130 # returns: True (1) if hash1 satisfies hash2, 0 if not. For example, with the
133 # %hash1 = { %hash2 = {
134 # 'class' => 'header' 'class' => '^h'
138 # the routine will return 1 if 'aContainmentType' equals 0, cause
139 # 'hash1' satisfies the conditions of 'hash2'. The routine will
140 # return 0 if 'aContainmentType' equals 1, cause 'hash1' doesn't
141 # exclude the conditions of 'hash2'.
142 # note: Class function.
144 sub _doesHashContainHash
{
146 my ($aHash1, $aHash2, $aContainmentType) = @_;
148 my ($key1, $value1, $key2, $value2, $result);
152 HASH2
: while (($key2, $value2) = each %$aHash2) {
153 # Yes, values are available;
155 $value1 = $aHash1->{$key2};
156 # Does value1 match criteria of value2?
157 if (defined($value1) && $value1 =~ m/$value2/) {
158 # Yes, value1 matches criteria of value2;
159 # Containment type was exclude?
160 if ($aContainmentType == CONTAINMENT_EXCLUDE
) {
161 # Yes, containment type was exclude;
162 # Indicate condition fails
164 # Reset 'each' iterator which we're going to break
171 # No, value1 didn't match criteria of value2;
172 # Containment type was include?
173 if ($aContainmentType == CONTAINMENT_INCLUDE
) {
174 # Yes, containment type was include;
175 # Indicate condition fails
177 # Reset 'each' iterator which we're going to break
186 } # _doesHashContainHash()
189 #--- HTML::TocGenerator::_extend() --------------------------------------------
190 # function: Extend ToC.
191 # - $aString: String to parse.
195 my ($self, $aFile) = @_;
199 $self->parse($aFile);
200 # Flush remaining buffered text
205 #--- HTML::TocGenerator::_extendFromFile() ------------------------------------
206 # function: Extend ToC.
207 # - $aFile: (reference to array of) file to parse.
209 sub _extendFromFile
{
211 my ($self, $aFile) = @_;
214 # Dereference array reference or make array of file specification
215 @files = (ref($aFile) =~ m/ARRAY/) ? @
$aFile : ($aFile);
217 foreach $file (@files) {
219 $self->{_currentFile
} = $file;
221 $self->parse_file($file);
222 # Flush remaining buffered text
225 } # _extendFromFile()
228 #--- HTML::TocGenerator::_formatHeadingLevel() --------------------------------
229 # function: Format heading level.
230 # args: - $aLevel: Level of current heading
231 # - $aClass: Class of current heading
232 # - $aGroup: Group of current heading
233 # - $aToc: Toc of current heading
235 sub _formatHeadingLevel
{
237 my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
239 my ($result, $headingNumber, $numberingStyle);
241 $headingNumber = $self->_getGroupIdManager($aToc)->
242 {levels
}{$aClass}[$aLevel - 1] || 0;
244 # Alias numbering style of current group
245 $numberingStyle = $aGroup->{numberingStyle
};
248 if ($numberingStyle eq "decimal") {
249 $result = $headingNumber;
252 if ($numberingStyle eq "lower-alpha") {
253 $result = chr($headingNumber + ord('a') - 1);
256 if ($numberingStyle eq "upper-alpha") {
257 $result = chr($headingNumber + ord('A') - 1);
260 if ($numberingStyle eq "lower-roman") {
262 $result = Roman
::roman
($headingNumber);
265 if ($numberingStyle eq "upper-roman") {
267 $result = Roman
::Roman
($headingNumber);
270 die "Unknown case: $numberingStyle";
274 } # _formatHeadingLevel()
277 #--- HTML::TocGenerator::_formatTocNode() -------------------------------------
278 # function: Format heading node.
279 # args: - $aLevel: Level of current heading
280 # - $aClass: Class of current heading
281 # - $aGroup: Group of current heading
282 # - $aToc: Toc of current heading
286 my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
288 my ($result, $level, $levelGroups);
290 # Alias 'levelGroups' of right 'groupId'
291 $levelGroups = $aToc->{_levelGroups
}{$aGroup->{'groupId'}};
292 # Loop through levels
293 for ($level = 1; $level <= $aLevel; $level++) {
294 # If not first level, add dot
295 $result = ($result ?
$result . "." : $result);
296 # Format heading level using argument group
297 $result .= $self->_formatHeadingLevel(
298 $level, $aClass, @
{$levelGroups}[$level - 1], $aToc
306 #--- HTML::TocGenerator::_generate() ------------------------------------------
307 # function: Generate ToC.
308 # args: - $aString: Reference to string to parse
312 my ($self, $aString) = @_;
316 foreach $toc (@
{$self->{_tocs
}}) {
321 $self->_extend($aString);
325 #--- HTML::TocGenerator::_generateFromFile() ----------------------------------
326 # function: Generate ToC.
327 # args: - $aFile: (reference to array of) file to parse.
329 sub _generateFromFile
{
331 my ($self, $aFile) = @_;
335 foreach $toc (@
{$self->{_tocs
}}) {
340 $self->_extendFromFile($aFile);
341 } # _generateFromFile()
344 #--- HTML::TocGenerator::_getGroupIdManager() ---------------------------------
345 # function: Get group id manager.
346 # args: - $aToc: Active ToC.
347 # returns: Group id levels.
349 sub _getGroupIdManager
{
351 my ($self, $aToc) = @_;
355 if ($self->{options
}{'doUseGroupsGlobal'}) {
356 # Yes, global groups;
365 } # _getGroupIdManager()
368 #--- HTML::TocGenerator::_initializeBatch() -----------------------------------
369 # function: Initialize batch. This function is called once when a parse batch
371 # args: - $aTocs: Reference to array of tocs.
373 sub _initializeBatch
{
375 my ($self, $aTocs) = @_;
379 # Store reference to tocs
381 # Is ToC specification reference to array?
382 if (ref($aTocs) =~ m/ARRAY/) {
383 # Yes, ToC specification is reference to array;
384 # Store array reference
385 $self->{_tocs
} = $aTocs;
388 # No, ToC specification is reference to ToC object;
389 # Wrap reference in array reference, containing only one element
390 $self->{_tocs
} = [$aTocs];
393 foreach $toc (@
{$self->{_tocs
}}) {
395 $toc->parseOptions();
397 } # _initializeBatch()
400 #--- HTML::TocGenerator::_initializeExtenderBatch() --------------------------
401 # function: Initialize 'extender' batch. This function is called once when a
402 # parse batch is started.
403 # args: - $aTocs: Reference to array of tocs.
405 sub _initializeExtenderBatch
{
407 my ($self, $aTocs) = @_;
408 # Do general batch initialization
409 $self->_initializeBatch($aTocs);
411 $self->_parseTocOptions();
412 # Indicate start of batch
413 $self->{_doGenerateToc
} = 1;
414 } # _initializeExtenderBatch()
417 #--- HTML::TocGenerator::_initializeGeneratorBatch() --------------------------
418 # function: Initialize generator batch. This function is called once when a
419 # parse batch is started.
420 # args: - $aTocs: Reference to array of tocs.
421 # - $aOptions: optional options
423 sub _initializeGeneratorBatch
{
425 my ($self, $aTocs, $aOptions) = @_;
426 # Add invocation options
427 $self->setOptions($aOptions);
428 # Option 'doUseGroupsGlobal' specified?
429 if (!defined($self->{options
}{'doUseGroupsGlobal'})) {
430 # No, options 'doUseGroupsGlobal' not specified;
431 # Default to no 'doUseGroupsGlobal'
432 $self->{options
}{'doUseGroupsGlobal'} = 0;
435 if ($self->{options
}{'doUseGroupsGlobal'}) {
436 # Yes, global groups;
437 # Reset groups and levels
438 $self->_resetStackVariables();
440 # Do 'extender' batch initialization
441 $self->_initializeExtenderBatch($aTocs);
442 } # _initializeGeneratorBatch()
445 #--- HTML::TocGenerator::_linkTocToToken() ------------------------------------
446 # function: Link ToC to token.
447 # args: - $aToc: ToC to add token to.
454 # - $aTokenAttributes: reference to hash containing attributes of
455 # currently parsed token
457 sub _linkTocToToken
{
460 $self, $aToc, $aFile, $aGroupId, $aLevel, $aNode, $aGroupLevel,
461 $aDoLinkToId, $aTokenAttributes
464 my ($file, $groupId, $level, $node, $anchorName);
465 my ($doInsertAnchor, $doInsertId);
467 # Fill local arguments to be used by templates
469 $groupId = $aGroupId;
473 # Assemble anchor name
475 ref($aToc->{_templateAnchorName
}) eq "CODE" ?
476 &{$aToc->{_templateAnchorName
}}(
477 $aFile, $aGroupId, $aLevel, $aNode
479 eval($aToc->{_templateAnchorName
});
481 # Bias to insert anchor name
487 # Indicate to insert anchor id
490 # Id attribute is available?
491 if (defined($aTokenAttributes->{id
})) {
492 # Yes, id attribute is available;
494 if ($aToc->{options
}{'doUseExistingIds'}) {
495 # Yes, use existing ids;
497 $anchorName = $aTokenAttributes->{id
};
498 # Indicate to not insert id
505 # No, link to 'name';
506 # Anchor name is currently active?
507 if (defined($self->{_activeAnchorName
})) {
508 # Yes, anchor name is currently active;
509 # Use existing anchors?
510 if ($aToc->{options
}{'doUseExistingAnchors'}) {
511 # Yes, use existing anchors;
512 # Use existing anchor name
513 $anchorName = $self->{_activeAnchorName
};
514 # Indicate to not insert anchor name
518 # No, don't use existing anchors; insert new anchor;
524 # Add reference to ToC
526 ref($aToc->{_templateAnchorHrefBegin
}) eq "CODE" ?
527 &{$aToc->{_templateAnchorHrefBegin
}}(
528 $aFile, $aGroupId, $aLevel, $aNode, $anchorName
530 eval($aToc->{_templateAnchorHrefBegin
});
532 # Bias to not output anchor name end
533 $self->{_doOutputAnchorNameEnd
} = 0;
534 # Must anchor be inserted?
535 if ($doInsertAnchor) {
536 # Yes, anchor must be inserted;
537 # Allow adding of anchor name begin token to text by calling
538 # 'anchorNameBegin' method
539 $self->anchorNameBegin(
540 ref($aToc->{_templateAnchorNameBegin
}) eq "CODE" ?
541 &{$aToc->{_templateAnchorNameBegin
}}(
542 $aFile, $aGroupId, $aLevel, $aNode, $anchorName
544 eval($aToc->{_templateAnchorNameBegin
}),
549 # Must anchorId attribute be inserted?
551 # Yes, anchorId attribute must be inserted;
552 # Allow adding of anchorId attribute to text by calling 'anchorId'
554 $self->anchorId($anchorName);
556 } # _linkTocToToken()
559 #--- HTML::TocGenerator::_outputAnchorNameEndConditionally() ------------------
560 # function: Output 'anchor name end' if necessary
561 # args: - $aToc: ToC of which 'anchor name end' must be output.
563 sub _outputAnchorNameEndConditionally
{
565 my ($self, $aToc) = @_;
566 # Must anchor name end be output?
567 if ($self->{_doOutputAnchorNameEnd
}) {
568 # Yes, output anchor name end;
569 # Allow adding of anchor to text by calling 'anchorNameEnd'
571 $self->anchorNameEnd(
572 ref($aToc->{_templateAnchorNameEnd
}) eq "CODE" ?
573 &{$aToc->{_templateAnchorNameEnd
}} :
574 eval($aToc->{_templateAnchorNameEnd
}),
578 } # _outputAnchorNameEndConditionally()
581 #--- HTML::TocGenerator::_parseTocOptions() -----------------------------------
582 # function: Parse ToC options.
584 sub _parseTocOptions
{
588 my ($toc, $group, $tokens, $tokenType, $i);
589 # Create parsers for ToC tokens
590 $self->{_tokensTocBegin
} = [];
591 my $tokenTocBeginParser = HTML
::_TokenTocBeginParser
->new(
592 $self->{_tokensTocBegin
}
594 my $tokenTocEndParser = HTML
::_TokenTocEndParser
->new();
596 foreach $toc (@
{$self->{_tocs
}}) {
597 # Reference parser ToC to current ToC
598 $tokenTocBeginParser->setToc($toc);
599 # Loop through 'tokenToToc' groups
600 foreach $group (@
{$toc->{options
}{'tokenToToc'}}) {
601 # Reference parser group to current group
602 $tokenTocBeginParser->setGroup($group);
603 # Parse 'tokenToToc' group
604 $tokenTocBeginParser->parse($group->{'tokenBegin'});
605 # Flush remaining buffered text
606 $tokenTocBeginParser->eof();
607 $tokenTocEndParser->parse(
608 $group->{'tokenEnd'},
609 $tokenTocBeginParser->{_lastAddedToken
},
610 $tokenTocBeginParser->{_lastAddedTokenType
}
612 # Flush remaining buffered text
613 $tokenTocEndParser->eof();
616 } # _parseTocOptions()
619 #--- HTML::TocGenerator::_processTocEndingToken() -----------------------------
620 # function: Process ToC-ending-token.
621 # args: - $aTocToken: token which acts as ToC-ending-token.
623 sub _processTocEndingToken
{
625 my ($self, $aTocToken) = @_;
629 $toc = $aTocToken->[TT_TOC
];
630 # Link ToC to tokens?
631 if ($toc->{options
}{'doLinkToToken'}) {
632 # Yes, link ToC to tokens;
633 # Add anchor href end
635 (ref($toc->{_templateAnchorHrefEnd
}) eq "CODE") ?
636 &{$toc->{_templateAnchorHrefEnd
}} :
637 eval($toc->{_templateAnchorHrefEnd
});
639 # Output anchor name end only if necessary
640 $self->_outputAnchorNameEndConditionally($toc);
642 } # _processTocEndingToken()
645 #--- HTML::TocGenerator::_processTocStartingToken() ---------------------------
646 # function: Process ToC-starting-token.
647 # args: - $aTocToken: token which acts as ToC-starting-token.
648 # - $aTokenType: type of token. Can be either TT_TOKENTYPE_START,
649 # _END, _TEXT, _COMMENT or _DECLARATION.
650 # - $aTokenAttributes: reference to hash containing attributes of
651 # currently parsed token
652 # - $aTokenOrigText: reference to original token text
654 sub _processTocStartingToken
{
656 my ($self, $aTocToken, $aTokenType, $aTokenAttributes, $aTokenOrigText) = @_;
658 my ($i, $level, $doLinkToId, $node, $groupLevel);
659 my ($file, $tocTokenId, $groupId, $toc, $attribute);
661 $file = $self->{_currentFile
};
662 $toc = $aTocToken->[TT_TOC
];
663 $level = $aTocToken->[TT_GROUP
]{'level'};
664 $groupId = $aTocToken->[TT_GROUP
]{'groupId'};
666 # Retrieve 'doLinkToId' setting from either group options or toc options
667 $doLinkToId = (defined($aTocToken->[TT_GROUP
]{'doLinkToId'})) ?
668 $aTocToken->[TT_GROUP
]{'doLinkToId'} : $toc->{options
}{'doLinkToId'};
670 # Link to 'id' and tokenType isn't 'start'?
671 if (($doLinkToId) && ($aTokenType != TT_TOKENTYPE_START
)) {
672 # Yes, link to 'id' and tokenType isn't 'start';
673 # Indicate to *not* link to 'id'
677 if (ref($level) eq "CODE") {
678 $level = &$level($self->{_currentFile
}, $node);
680 if (ref($groupId) eq "CODE") {
681 $groupId = &$groupId($self->{_currentFile
}, $node);
684 # Determine class level
686 my $groupIdManager = $self->_getGroupIdManager($toc);
688 if (!exists($groupIdManager->{groupIdLevels
}{$groupId})) {
691 $groupIdManager->{groupIdLevels
}{$groupId} = keys(
692 %{$groupIdManager->{groupIdLevels
}}
695 $groupLevel = $groupIdManager->{groupIdLevels
}{$groupId};
697 # Temporarily allow symbolic references
700 $groupIdManager->{levels
}{$groupId}[$level - 1] += 1;
701 # Reset remaining levels of same group
702 for ($i = $level; $i < @
{$groupIdManager->{levels
}{$groupId}}; $i++) {
703 $groupIdManager->{levels
}{$groupId}[$i] = 0;
706 # Assemble numeric string indicating current level
707 $node = $self->_formatTocNode(
708 $level, $groupId, $aTocToken->[TT_GROUP
], $toc
711 # Add newline if _toc not empty
713 $toc->{_toc
} .= "\n";
717 $toc->{_toc
} .= "$level $groupLevel $groupId $node " .
718 $groupIdManager->{levels
}{$groupId}[$level - 1] . " ";
720 # Add value of 'id' attribute if available
721 if (defined($aTokenAttributes->{id
})) {
722 $toc->{_toc
} .= $aTokenAttributes->{id
};
725 # Link ToC to tokens?
726 if ($toc->{options
}{'doLinkToToken'}) {
727 # Yes, link ToC to tokens;
729 $self->_linkTocToToken(
730 $toc, $file, $groupId, $level, $node, $groupLevel, $doLinkToId,
737 $aTocToken->[TT_GROUP
]{'doNumberToken'} ||
739 ! defined($aTocToken->[TT_GROUP
]{'doNumberToken'}) &&
740 $toc->{options
}{'doNumberToken'}
743 # Yes, number tokens;
744 # Add number by calling 'number' method
746 ref($toc->{_templateTokenNumber
}) eq "CODE" ?
747 &{$toc->{_templateTokenNumber
}}(
748 $node, $groupId, $file, $groupLevel, $level, $toc
750 eval($toc->{_templateTokenNumber
}),
755 # Must attribute be used as ToC text?
756 if (defined($aTocToken->[TT_ATTRIBUTES_TOC
])) {
757 # Yes, attribute must be used as ToC text;
758 # Loop through attributes
759 foreach $attribute (@
{$aTocToken->[TT_ATTRIBUTES_TOC
]}) {
760 # Attribute is available?
761 if (defined($$aTokenAttributes{$attribute})) {
762 # Yes, attribute is available;
763 # Add attribute value to ToC
764 $self->_processTocText($$aTokenAttributes{$attribute}, $toc);
767 # No, attribute isn't available;
770 WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS
,
771 [$attribute, $$aTokenOrigText]
774 # Output anchor name end only if necessary
775 #$self->_outputAnchorNameEndConditionally($toc);
777 $self->_processTocEndingToken($aTocToken);
781 # No, attribute mustn't be used as ToC text;
782 # Add end token to 'end token array'
784 @
{$self->{_tokensTocEnd
}[$aTocToken->[TT_TAG_TYPE_END
]]}, $aTocToken
787 } # _processTocStartingToken()
790 #--- HTML::TocGenerator::_processTocText() ------------------------------------
791 # function: This function processes text which must be added to the preliminary
793 # args: - $aText: Text to add to ToC.
794 # - $aToc: ToC to add text to.
796 sub _processTocText
{
798 my ($self, $aText, $aToc) = @_;
800 $aToc->{_toc
} .= $aText;
801 } # _processTocText()
804 #--- HTML::TocGenerator::_processTokenAsTocEndingToken() ----------------------
805 # function: Check for token being a token to use for triggering the end of
806 # a ToC line and process it accordingly.
807 # args: - $aTokenType: type of token: 'start', 'end', 'comment' or 'text'.
808 # - $aTokenId: token id of currently parsed token
810 sub _processTokenAsTocEndingToken
{
812 my ($self, $aTokenType, $aTokenId) = @_;
814 my ($i, $tokenId, $toc, $tokens);
815 # Loop through dirty start tokens
818 # Alias token array of right type
819 $tokens = $self->{_tokensTocEnd
}[$aTokenType];
820 # Loop through token array
821 while ($i < scalar @
$tokens) {
823 $tokenId = $tokens->[$i][TT_TAG_END
];
824 # Does current end tag equals dirty tag?
825 if ($aTokenId eq $tokenId) {
826 # Yes, current end tag equals dirty tag;
827 # Process ToC-ending-token
828 $self->_processTocEndingToken($tokens->[$i]);
829 # Remove dirty tag from array, automatically advancing to
831 splice(@
$tokens, $i, 1);
834 # No, current end tag doesn't equal dirty tag;
835 # Advance to next token
839 } # _processTokenAsTocEndingToken()
842 #--- HTML::TocGenerator::_processTokenAsTocStartingToken() --------------------
843 # function: Check for token being a ToC-starting-token and process it
845 # args: - $aTokenType: type of token. Can be either TT_TOKENTYPE_START,
846 # _END, _TEXT, _COMMENT or _DECLARATION.
847 # - $aTokenId: token id of currently parsed token
848 # - $aTokenAttributes: reference to hash containing attributes of
849 # currently parsed token
850 # - $aTokenOrigText: reference to original text of token
851 # returns: 1 if successful, i.e. token is processed as ToC-starting-token, 0
854 sub _processTokenAsTocStartingToken
{
856 my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aTokenOrigText) = @_;
858 my ($level, $levelToToc, $groupId, $groupToToc);
859 my ($result, $tocToken, $tagBegin, @tokensTocBegin, $fileSpec);
860 # Bias to token not functioning as ToC-starting-token
862 # Loop through start tokens of right type
863 foreach $tocToken (@
{$self->{_tokensTocBegin
}[$aTokenType]}) {
865 $fileSpec = $tocToken->[TT_GROUP
]{'fileSpec'};
867 if (!defined($fileSpec) || (
868 defined($fileSpec) &&
869 ($self->{_currentFile
} =~ m/$fileSpec/)
873 $tagBegin = $tocToken->[TT_TAG_BEGIN
];
874 # Tag and attributes match?
876 defined($tagBegin) &&
877 ($aTokenId =~ m/$tagBegin/) &&
878 HTML
::TocGenerator
::_doesHashContainHash
(
879 $aTokenAttributes, $tocToken->[TT_INCLUDE_ATTRIBUTES_BEGIN
], 0
881 HTML
::TocGenerator
::_doesHashContainHash
(
882 $aTokenAttributes, $tocToken->[TT_EXCLUDE_ATTRIBUTES_BEGIN
], 1
885 # Yes, tag and attributes match;
887 $level = $tocToken->[TT_GROUP
]{'level'};
888 $levelToToc = $tocToken->[TT_TOC
]{options
}{'levelToToc'};
889 $groupId = $tocToken->[TT_GROUP
]{'groupId'};
890 $groupToToc = $tocToken->[TT_TOC
]{options
}{'groupToToc'};
891 # Must level and group be processed?
893 ($level =~ m/$levelToToc/) &&
894 ($groupId =~ m/$groupToToc/)
896 # Yes, level and group must be processed;
897 # Indicate token acts as ToC-starting-token
899 # Process ToC-starting-token
900 $self->_processTocStartingToken(
901 $tocToken, $aTokenType, $aTokenAttributes, $aTokenOrigText
909 } # _processTokenAsTocStartingToken()
912 #--- HTML::TocGenerator::_resetBatchVariables() -------------------------------
913 # function: Reset variables which are set because of batch invocation.
915 sub _resetBatchVariables
{
919 # Filename of current file being parsed, empty string if not available
920 $self->{_currentFile
} = "";
921 # Arrays containing start, end, comment, text & declaration tokens which
922 # must trigger the ToC assembling. Each array element may contain a
923 # reference to an array containing the following elements:
927 # TT_TAG_TYPE_END => 2;
928 # TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
929 # TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
930 # TT_INCLUDE_ATTRIBUTES_END => 5;
931 # TT_EXCLUDE_ATTRIBUTES_END => 6;
934 # TT_ATTRIBUTES_TOC => 9;
936 $self->{_tokensTocBegin
} = [
937 [], # TT_TOKENTYPE_START
938 [], # TT_TOKENTYPE_END
939 [], # TT_TOKENTYPE_COMMENT
940 [], # TT_TOKENTYPE_TEXT
941 [] # TT_TOKENTYPE_DECLARATION
943 $self->{_tokensTocEnd
} = [
944 [], # TT_TOKENTYPE_START
945 [], # TT_TOKENTYPE_END
946 [], # TT_TOKENTYPE_COMMENT
947 [], # TT_TOKENTYPE_TEXT
948 [] # TT_TOKENTYPE_DECLARATION
950 # TRUE if ToCs have been initialized, FALSE if not.
951 $self->{_doneInitializeTocs
} = 0;
952 # Array of ToCs to process
955 $self->{_activeAnchorName
} = undef;
956 } # _resetBatchVariables()
959 #--- HTML::TocGenerator::_resetStackVariables() -------------------------------
960 # function: Reset variables which cumulate during ToC generation.
962 sub _resetStackVariables
{
966 $self->{levels
} = undef;
967 $self->{groupIdLevels
} = undef;
968 } # _resetStackVariables()
971 #--- HTML::TocGenerator::_setActiveAnchorName() -------------------------------
972 # function: Set active anchor name.
973 # args: - aAnchorName: Name of anchor name to set active.
975 sub _setActiveAnchorName
{
977 my ($self, $aAnchorName) = @_;
978 # Set active anchor name
979 $self->{_activeAnchorName
} = $aAnchorName;
980 } # _setActiveAnchorName()
983 #--- HTML::TocGenerator::_showWarning() ---------------------------------------
984 # function: Show warning.
985 # args: - aWarningNr: Number of warning to show.
986 # - aWarningArgs: Arguments to display within the warning.
990 my ($self, $aWarningNr, $aWarningArgs) = @_;
995 WARNING_NESTED_ANCHOR_PS_WITHIN_PS
() =>
996 "Nested anchor '%s' within anchor '%s'.",
997 WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS
() =>
998 "ToC attribute '%s' not available within token '%s'.",
1001 print STDERR
"warning ($aWarningNr): " . sprintf($warnings{"$aWarningNr"}, @
$aWarningArgs) . "\n";
1005 #--- HTML::TocGenerator::anchorId() -------------------------------------------
1006 # function: Anchor id processing method. Leave it up to the descendant to do
1007 # something useful with it.
1008 # args: - $aAnchorId
1009 # - $aToc: Reference to ToC to which anchorId belongs.
1015 #--- HTML::TocGenerator::anchorNameBegin() ------------------------------------
1016 # function: Anchor name begin processing method. Leave it up to the descendant
1017 # to do something useful with it.
1018 # args: - $aAnchorName
1019 # - $aToc: Reference to ToC to which anchorname belongs.
1021 sub anchorNameBegin
{
1022 } # anchorNameBegin()
1025 #--- HTML::TocGenerator::anchorNameEnd() --------------------------------------
1026 # function: Anchor name end processing method. Leave it up to the descendant
1027 # to do something useful with it.
1028 # args: - $aAnchorName
1029 # - $aToc: Reference to ToC to which anchorname belongs.
1035 #--- HTML::TocGenerator::comment() --------------------------------------------
1036 # function: Process comment.
1037 # args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
1041 my ($self, $aComment) = @_;
1042 # Must a ToC be generated?
1043 if ($self->{_doGenerateToc
}) {
1044 # Yes, a ToC must be generated
1045 # Process end tag as ToC-starting-token
1046 $self->_processTokenAsTocStartingToken(
1047 TT_TOKENTYPE_COMMENT
, $aComment, undef, \
$aComment
1049 # Process end tag as token which ends ToC registration
1050 $self->_processTokenAsTocEndingToken(
1051 TT_TOKENTYPE_COMMENT
, $aComment
1057 #--- HTML::TocGenerator::end() ------------------------------------------------
1058 # function: This function is called every time a closing tag is encountered.
1059 # args: - $aTag: tag name (in lower case).
1060 # - $aOrigText: tag name including brackets.
1064 my ($self, $aTag, $aOrigText) = @_;
1066 my ($tag, $toc, $i);
1067 # Must a ToC be generated?
1068 if ($self->{_doGenerateToc
}) {
1069 # Yes, a ToC must be generated
1070 # Process end tag as ToC-starting-token
1071 $self->_processTokenAsTocStartingToken(
1072 TT_TOKENTYPE_END
, $aTag, undef, \
$aOrigText
1074 # Process end tag as ToC-ending-token
1075 $self->_processTokenAsTocEndingToken(
1076 TT_TOKENTYPE_END
, $aTag
1078 # Tag is of type 'anchor'?
1079 if (defined($self->{_activeAnchorName
}) && ($aTag eq "a")) {
1080 # Yes, tag is of type 'anchor';
1081 # Reset dirty anchor
1082 $self->{_activeAnchorName
} = undef;
1088 #--- HTML::TocGenerator::extend() ---------------------------------------------
1089 # function: Extend ToCs.
1090 # args: - $aTocs: Reference to array of ToC objects
1091 # - $aString: String to parse.
1095 my ($self, $aTocs, $aString) = @_;
1096 # Initialize TocGenerator batch
1097 $self->_initializeExtenderBatch($aTocs);
1099 $self->_extend($aString);
1100 # Deinitialize TocGenerator batch
1101 $self->_deinitializeExtenderBatch();
1105 #--- HTML::TocGenerator::extendFromFile() -------------------------------------
1106 # function: Extend ToCs.
1107 # args: - @aTocs: Reference to array of ToC objects
1108 # - @aFiles: Reference to array of files to parse.
1110 sub extendFromFile
{
1112 my ($self, $aTocs, $aFiles) = @_;
1113 # Initialize TocGenerator batch
1114 $self->_initializeExtenderBatch($aTocs);
1116 $self->_extendFromFile($aFiles);
1117 # Deinitialize TocGenerator batch
1118 $self->_deinitializeExtenderBatch();
1119 } # extendFromFile()
1122 #--- HTML::TocGenerator::generate() -------------------------------------------
1123 # function: Generate ToC.
1124 # args: - $aToc: Reference to (array of) ToC object(s)
1125 # - $aString: Reference to string to parse
1126 # - $aOptions: optional options
1130 my ($self, $aToc, $aString, $aOptions) = @_;
1131 # Initialize TocGenerator batch
1132 $self->_initializeGeneratorBatch($aToc, $aOptions);
1134 $self->_generate($aString);
1135 # Deinitialize TocGenerator batch
1136 $self->_deinitializeGeneratorBatch();
1140 #--- HTML::TocGenerator::generateFromFile() -----------------------------------
1141 # function: Generate ToC.
1142 # args: - $aToc: Reference to (array of) ToC object(s)
1143 # - $aFile: (reference to array of) file to parse.
1144 # - $aOptions: optional options
1146 sub generateFromFile
{
1148 my ($self, $aToc, $aFile, $aOptions) = @_;
1149 # Initialize TocGenerator batch
1150 $self->_initializeGeneratorBatch($aToc, $aOptions);
1152 $self->_generateFromFile($aFile);
1153 # Deinitialize TocGenerator batch
1154 $self->_deinitializeGeneratorBatch();
1155 } # generateFromFile()
1158 #--- HTML::TocGenerator::number() ---------------------------------------------
1159 # function: Heading number processing method. Leave it up to the descendant
1160 # to do something useful with it.
1162 # - $aToc: Reference to ToC to which anchorname belongs.
1166 my ($self, $aNumber, $aToc) = @_;
1170 #--- HTML::TocGenerator::parse() ----------------------------------------------
1171 # function: Parse scalar.
1172 # args: - $aString: string to parse
1176 my ($self, $aString) = @_;
1178 $self->SUPER::parse
($aString);
1182 #--- HTML::TocGenerator::parse_file() -----------------------------------------
1183 # function: Parse file.
1187 my ($self, $aFile) = @_;
1189 $self->SUPER::parse_file
($aFile);
1193 #--- HTML::TocGenerator::setOptions() -----------------------------------------
1194 # function: Set options.
1195 # args: - aOptions: Reference to hash containing options.
1199 my ($self, $aOptions) = @_;
1200 # Options are defined?
1201 if (defined($aOptions)) {
1202 # Yes, options are defined; add to options
1203 %{$self->{options
}} = (%{$self->{options
}}, %$aOptions);
1208 #--- HTML::TocGenerator::start() ----------------------------------------------
1209 # function: This function is called every time an opening tag is encountered.
1210 # args: - $aTag: tag name (in lower case).
1211 # - $aAttr: reference to hash containing all tag attributes (in lower
1213 # - $aAttrSeq: reference to array containing all tag attributes (in
1214 # lower case) in the original order
1215 # - $aOrigText: the original HTML text
1219 my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1220 $self->{isTocToken
} = 0;
1221 # Start tag is of type 'anchor name'?
1222 if ($aTag eq "a" && defined($aAttr->{name
})) {
1223 # Yes, start tag is of type 'anchor name';
1224 # Is another anchor already active?
1225 if (defined($self->{_activeAnchorName
})) {
1226 # Yes, another anchor is already active;
1227 # Is the first anchor inserted by 'TocGenerator'?
1228 if ($self->{_doOutputAnchorNameEnd
}) {
1229 # Yes, the first anchor is inserted by 'TocGenerator';
1231 $self->_showWarning(
1232 WARNING_NESTED_ANCHOR_PS_WITHIN_PS
,
1233 [$aOrigText, $self->{_activeAnchorName
}]
1237 # Set active anchor name
1238 $self->_setActiveAnchorName($aAttr->{name
});
1240 # Must a ToC be generated?
1241 if ($self->{_doGenerateToc
}) {
1242 # Yes, a ToC must be generated
1243 # Process start tag as ToC token
1244 $self->{isTocToken
} = $self->_processTokenAsTocStartingToken(
1245 TT_TOKENTYPE_START
, $aTag, $aAttr, \
$aOrigText
1247 # Process end tag as ToC-ending-token
1248 $self->_processTokenAsTocEndingToken(
1249 TT_TOKENTYPE_START
, $aTag
1255 #--- HTML::TocGenerator::text() -----------------------------------------------
1256 # function: This function is called every time plain text is encountered.
1257 # args: - @_: array containing data.
1261 my ($self, $aText) = @_;
1263 my ($text, $toc, $i, $token, $tokens);
1264 # Must a ToC be generated?
1265 if ($self->{_doGenerateToc
}) {
1266 # Yes, a ToC must be generated
1267 # Are there dirty start tags?
1269 # Loop through token types
1270 foreach $tokens (@
{$self->{_tokensTocEnd
}}) {
1271 # Loop though tokens
1272 foreach $token (@
$tokens) {
1276 $toc = $token->[TT_TOC
];
1277 # Remove possible newlines from text
1278 ($text = $aText) =~ s/\s*\n\s*/ /g;
1280 $self->_processTocText($text, $toc);
1289 #=== HTML::_TokenTocParser ====================================================
1290 # function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1291 # inserted into the ToC.
1292 # note: Used internally.
1294 package HTML
::_TokenTocParser
;
1300 @ISA = qw(HTML::Parser);
1307 #--- HTML::_TokenTocParser::new() ---------------------------------------------
1308 # function: Constructor
1314 my $self = $aType->SUPER::new
;
1321 #--- HTML::_TokenTocParser::_parseAttributes() --------------------------------
1322 # function: Parse attributes.
1323 # args: - $aAttr: Reference to hash containing all tag attributes (in lower
1325 # - $aIncludeAttributes: Reference to hash to which 'include
1326 # attributes' must be added.
1327 # - $aExcludeAttributes: Reference to hash to which 'exclude
1328 # attributes' must be added.
1329 # - $aTocAttributes: Reference to hash to which 'ToC attributes'
1332 sub _parseAttributes
{
1335 $self, $aAttr, $aIncludeAttributes, $aExcludeAttributes,
1340 my ($attributeToExcludeToken, $attributeToTocToken);
1341 # Get token which marks attributes which must be excluded
1342 $attributeToExcludeToken = $self->{_toc
}{options
}{'attributeToExcludeToken'};
1343 $attributeToTocToken = $self->{_toc
}{options
}{'attributeToTocToken'};
1344 # Loop through attributes
1345 while (($key, $value) = each %$aAttr) {
1346 # Attribute value equals 'ToC token'?
1347 if ($value =~ m/$attributeToTocToken/) {
1348 # Yes, attribute value equals 'ToC token';
1349 # Add attribute to 'ToC attributes'
1350 push @
$aTocAttributes, $key;
1353 # No, attribute isn't 'ToC' token;
1354 # Attribute value starts with 'exclude token'?
1355 if ($value =~ m/^$attributeToExcludeToken(.*)/) {
1356 # Yes, attribute value starts with 'exclude token';
1357 # Add attribute to 'exclude attributes'
1358 $$aExcludeAttributes{$key} = "$1";
1361 # No, attribute key doesn't start with '-';
1362 # Add attribute to 'include attributes'
1363 $$aIncludeAttributes{$key} = $value;
1367 } # _parseAttributes()
1372 #=== HTML::_TokenTocBeginParser ===============================================
1373 # function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1374 # inserted into the ToC.
1375 # note: Used internally.
1377 package HTML
::_TokenTocBeginParser
;
1383 @ISA = qw(HTML::_TokenTocParser);
1389 #--- HTML::_TokenTocBeginParser::new() ----------------------------------------
1390 # function: Constructor
1394 my ($aType, $aTokenArray) = @_;
1396 my $self = $aType->SUPER::new
;
1397 # Reference token array
1398 $self->{tokens
} = $aTokenArray;
1399 # Reference to last added token
1400 $self->{_lastAddedToken
} = undef;
1401 $self->{_lastAddedTokenType
} = undef;
1407 #--- HTML::_TokenTocBeginParser::_processAttributes() -------------------------
1408 # function: Process attributes.
1409 # args: - $aAttributes: Attributes to parse.
1411 sub _processAttributes
{
1413 my ($self, $aAttributes) = @_;
1415 my (%includeAttributes, %excludeAttributes, @tocAttributes);
1418 $self->_parseAttributes(
1419 $aAttributes, \
%includeAttributes, \
%excludeAttributes, \
@tocAttributes
1421 # Include attributes are specified?
1422 if (keys(%includeAttributes) > 0) {
1423 # Yes, include attributes are specified;
1424 # Store include attributes
1425 @
${$self->{_lastAddedToken
}}[
1426 HTML
::TocGenerator
::TT_INCLUDE_ATTRIBUTES_BEGIN
1427 ] = \
%includeAttributes;
1429 # Exclude attributes are specified?
1430 if (keys(%excludeAttributes) > 0) {
1431 # Yes, exclude attributes are specified;
1432 # Store exclude attributes
1433 @
${$self->{_lastAddedToken
}}[
1434 HTML
::TocGenerator
::TT_EXCLUDE_ATTRIBUTES_BEGIN
1435 ] = \
%excludeAttributes;
1437 # Toc attributes are specified?
1438 if (@tocAttributes > 0) {
1439 # Yes, toc attributes are specified;
1440 # Store toc attributes
1441 @
${$self->{_lastAddedToken
}}[
1442 HTML
::TocGenerator
::TT_ATTRIBUTES_TOC
1443 ] = \
@tocAttributes;
1445 } # _processAttributes()
1448 #--- HTML::_TokenTocBeginParser::_processToken() ------------------------------
1449 # function: Process token.
1450 # args: - $aTokenType: Type of token to process.
1451 # - $aTag: Tag of token.
1455 my ($self, $aTokenType, $aTag) = @_;
1457 my ($tokenArray, $index);
1458 # Push element on array of update tokens
1459 $index = push(@
{$self->{tokens
}[$aTokenType]}, []) - 1;
1460 # Alias token array to add element to
1461 $tokenArray = $self->{tokens
}[$aTokenType];
1462 # Indicate last updated token array element
1463 $self->{_lastAddedTokenType
} = $aTokenType;
1464 $self->{_lastAddedToken
} = \
$$tokenArray[$index];
1466 $$tokenArray[$index][HTML
::TocGenerator
::TT_TAG_BEGIN
] = $aTag;
1467 $$tokenArray[$index][HTML
::TocGenerator
::TT_GROUP
] = $self->{_group
};
1468 $$tokenArray[$index][HTML
::TocGenerator
::TT_TOC
] = $self->{_toc
};
1472 #--- HTML::_TokenTocBeginParser::comment() ------------------------------------
1473 # function: Process comment.
1474 # args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
1478 my ($self, $aComment) = @_;
1480 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_COMMENT
, $aComment);
1484 #--- HTML::_TokenTocBeginParser::declaration() --------------------------------
1485 # function: This function is called every time a markup declaration is
1486 # encountered by HTML::Parser.
1487 # args: - $aDeclaration: Markup declaration.
1491 my ($self, $aDeclaration) = @_;
1493 $self->_processToken(
1494 HTML
::TocGenerator
::TT_TOKENTYPE_DECLARATION
, $aDeclaration
1499 #--- HTML::_TokenTocBeginParser::end() ----------------------------------------
1500 # function: This function is called every time a closing tag is encountered
1502 # args: - $aTag: tag name (in lower case).
1506 my ($self, $aTag, $aOrigText) = @_;
1508 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_END
, $aTag);
1512 #--- HTML::_TokenTocBeginParser::parse() --------------------------------------
1513 # function: Parse begin token.
1514 # args: - $aToken: 'toc token' to parse
1518 my ($self, $aString) = @_;
1520 $self->SUPER::parse
($aString);
1524 #--- HTML::_TokenTocBeginParser->setGroup() -----------------------------------
1525 # function: Set current 'tokenToToc' group.
1529 my ($self, $aGroup) = @_;
1530 # Set current 'tokenToToc' group
1531 $self->{_group
} = $aGroup;
1535 #--- HTML::_TokenTocBeginParser->setToc() -------------------------------------
1536 # function: Set current ToC.
1540 my ($self, $aToc) = @_;
1542 $self->{_toc
} = $aToc;
1546 #--- HTML::_TokenTocBeginParser::start() --------------------------------------
1547 # function: This function is called every time an opening tag is encountered.
1548 # args: - $aTag: tag name (in lower case).
1549 # - $aAttr: reference to hash containing all tag attributes (in lower
1551 # - $aAttrSeq: reference to array containing all attribute keys (in
1552 # lower case) in the original order
1553 # - $aOrigText: the original HTML text
1557 my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1559 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_START
, $aTag);
1560 # Process attributes
1561 $self->_processAttributes($aAttr);
1565 #--- HTML::_TokenTocBeginParser::text() ---------------------------------------
1566 # function: This function is called every time plain text is encountered.
1567 # args: - @_: array containing data.
1571 my ($self, $aText) = @_;
1572 # Was token already created and is last added token of type 'text'?
1574 defined($self->{_lastAddedToken
}) &&
1575 $self->{_lastAddedTokenType
} == HTML
::TocGenerator
::TT_TOKENTYPE_TEXT
1577 # Yes, token is already created;
1578 # Add tag to existing token
1579 @
${$self->{_lastAddedToken
}}[HTML
::TocGenerator
::TT_TAG_BEGIN
] .= $aText;
1582 # No, token isn't created;
1584 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_TEXT
, $aText);
1591 #=== HTML::_TokenTocEndParser =================================================
1592 # function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1593 # inserted into the ToC.
1594 # note: Used internally.
1596 package HTML
::_TokenTocEndParser
;
1602 @ISA = qw(HTML::_TokenTocParser);
1609 #--- HTML::_TokenTocEndParser::new() ------------------------------------------
1610 # function: Constructor
1611 # args: - $aType: Class type.
1617 my $self = $aType->SUPER::new
;
1618 # Reference to last added token
1619 $self->{_lastAddedToken
} = undef;
1625 #--- HTML::_TokenTocEndParser::_processAttributes() ---------------------------
1626 # function: Process attributes.
1627 # args: - $aAttributes: Attributes to parse.
1629 sub _processAttributes
{
1631 my ($self, $aAttributes) = @_;
1633 my (%includeAttributes, %excludeAttributes);
1636 $self->_parseAttributes(
1637 $aAttributes, \
%includeAttributes, \
%excludeAttributes
1639 # Include attributes are specified?
1640 if (keys(%includeAttributes) > 0) {
1641 # Yes, include attributes are specified;
1642 # Store include attributes
1643 @
${$self->{_Token
}}[
1644 HTML
::TocGenerator
::TT_INCLUDE_ATTRIBUTES_END
1645 ] = \
%includeAttributes;
1647 # Exclude attributes are specified?
1648 if (keys(%excludeAttributes) > 0) {
1649 # Yes, exclude attributes are specified;
1650 # Store exclude attributes
1651 @
${$self->{_Token
}}[
1652 HTML
::TocGenerator
::TT_EXCLUDE_ATTRIBUTES_END
1653 ] = \
%excludeAttributes;
1655 } # _processAttributes()
1658 #--- HTML::_TokenTocEndParser::_processToken() --------------------------------
1659 # function: Process token.
1660 # args: - $aTokenType: Type of token to process.
1661 # - $aTag: Tag of token.
1665 my ($self, $aTokenType, $aTag) = @_;
1667 @
${$self->{_token
}}[HTML
::TocGenerator
::TT_TAG_TYPE_END
] = $aTokenType;
1668 @
${$self->{_token
}}[HTML
::TocGenerator
::TT_TAG_END
] = $aTag;
1669 # Indicate token type which has been processed
1670 $self->{_lastAddedTokenType
} = $aTokenType;
1674 #--- HTML::_TokenTocEndParser::comment() --------------------------------------
1675 # function: Process comment.
1676 # args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
1680 my ($self, $aComment) = @_;
1682 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_COMMENT
, $aComment);
1686 #--- HTML::_TokenTocDeclarationParser::declaration() --------------------------
1687 # function: This function is called every time a markup declaration is
1688 # encountered by HTML::Parser.
1689 # args: - $aDeclaration: Markup declaration.
1693 my ($self, $aDeclaration) = @_;
1695 $self->_processToken(
1696 HTML
::TocGenerator
::TT_TOKENTYPE_DECLARATION
, $aDeclaration
1701 #--- HTML::_TokenTocEndParser::end() ------------------------------------------
1702 # function: This function is called every time a closing tag is encountered
1704 # args: - $aTag: tag name (in lower case).
1708 my ($self, $aTag, $aOrigText) = @_;
1710 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_END
, $aTag);
1714 #--- HTML::_TokenTocEndParser::parse() ----------------------------------------
1715 # function: Parse token.
1716 # args: - $aString: 'toc token' to parse
1717 # - $aToken: Reference to token
1718 # - $aTokenTypeBegin: Type of begin token
1722 my ($self, $aString, $aToken, $aTokenTypeBegin) = @_;
1723 # Token argument specified?
1724 if (defined($aToken)) {
1725 # Yes, token argument is specified;
1726 # Store token reference
1727 $self->{_token
} = $aToken;
1730 if (! defined($aString)) {
1731 # No, end tag isn't defined;
1732 # Last added tokentype was of type 'start'?
1734 (defined($aTokenTypeBegin)) &&
1735 ($aTokenTypeBegin == HTML
::TocGenerator
::TT_TOKENTYPE_START
)
1737 # Yes, last added tokentype was of type 'start';
1739 $self->_processToken(
1740 HTML
::TocGenerator
::TT_TAG_END
,
1741 @
${$self->{_token
}}[HTML
::TocGenerator
::TT_TAG_BEGIN
]
1747 $self->SUPER::parse
($aString);
1752 #--- HTML::_TokenTocEndParser::start() ----------------------------------------
1753 # function: This function is called every time an opening tag is encountered.
1754 # args: - $aTag: tag name (in lower case).
1755 # - $aAttr: reference to hash containing all tag attributes (in lower
1757 # - $aAttrSeq: reference to array containing all attribute keys (in
1758 # lower case) in the original order
1759 # - $aOrigText: the original HTML text
1763 my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1765 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_START
, $aTag);
1766 # Process attributes
1767 $self->_processAttributes($aAttr);
1771 #--- HTML::_TokenTocEndParser::text() -----------------------------------------
1772 # function: This function is called every time plain text is encountered.
1773 # args: - @_: array containing data.
1777 my ($self, $aText) = @_;
1779 # Is token already created?
1780 if (defined($self->{_lastAddedTokenType
})) {
1781 # Yes, token is already created;
1782 # Add tag to existing token
1783 @
${$self->{_token
}}[HTML
::TocGenerator
::TT_TAG_END
] .= $aText;
1786 # No, token isn't created;
1788 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_TEXT
, $aText);