1 #--- TocInsertor.pm -----------------------------------------------------------
2 # function: Insert Table of Contents HTML::Toc, generated by
4 # note: - The term 'propagate' is used as a shortcut for the process of
5 # both generating and inserting a ToC at the same time.
6 # - 'TIP' is an abbreviation of 'Toc Insertion Point'.
9 package HTML
::TocInsertor
;
14 use HTML
::TocGenerator
;
18 use vars
qw(@ISA $VERSION);
22 @ISA = qw(HTML::TocGenerator);
25 # TocInsertionPoint (TIP) constants
27 use constant TIP_PREPOSITION_REPLACE
=> 'replace';
28 use constant TIP_PREPOSITION_BEFORE
=> 'before';
29 use constant TIP_PREPOSITION_AFTER
=> 'after';
31 use constant TIP_TOKEN_ID
=> 0;
32 use constant TIP_PREPOSITION
=> 1;
33 use constant TIP_INCLUDE_ATTRIBUTES
=> 2;
34 use constant TIP_EXCLUDE_ATTRIBUTES
=> 3;
35 use constant TIP_TOC
=> 4;
37 use constant MODE_DO_NOTHING
=> 0; # 0b00
38 use constant MODE_DO_INSERT
=> 1; # 0b01
39 use constant MODE_DO_PROPAGATE
=> 3; # 0b11
44 #--- HTML::TocInsertor::new() -------------------------------------------------
45 # function: Constructor.
50 my $self = $aType->SUPER::new
;
51 # TRUE if insertion point token must be output, FALSE if not
52 $self->{_doOutputInsertionPointToken
} = 1;
53 # Reset batch variables
54 $self->_resetBatchVariables;
55 # Bias to not insert ToC
56 $self->{hti__Mode
} = MODE_DO_NOTHING
;
58 # TODO: Initialize output
64 #--- HTML::TocInsertor::_deinitializeOutput() ---------------------------------
65 # function: Deinitialize output.
67 sub _deinitializeOutput
{
70 # Filehandle is defined?
71 if (defined($self->{_outputFileHandle
})) {
72 # Yes, filehandle is defined;
73 # Restore selected filehandle
74 select($self->{_oldFileHandle
});
75 # Undefine filehandle, closing it automatically
76 undef $self->{_outputFileHandle
};
78 } # _deinitializeOutput()
81 #--- HTML::TocInsertor::_initializeOutput() -----------------------------------
82 # function: Initialize output.
84 sub _initializeOutput
{
87 # Bias to write to outputfile
88 my $doOutputToFile = 1;
90 # Is output specified?
91 if (defined($self->{options
}{'output'})) {
92 # Yes, output is specified;
93 # Indicate to not output to outputfile
95 # Alias output reference
96 $self->{_output
} = $self->{options
}{'output'};
98 ${$self->{_output
}} = "";
101 # Is output file specified?
102 if (defined($self->{options
}{'outputFile'})) {
103 # Yes, output file is specified;
104 # Indicate to output to outputfile
107 $self->{_outputFileHandle
} =
108 new FileHandle
">" . $self->{options
}{'outputFile'};
110 # Backup currently selected filehandle
111 $self->{_oldFileHandle
} = select;
112 # Set new default filehandle
113 select($self->{_outputFileHandle
});
116 # Alias output-to-file indicator
117 $self->{_doOutputToFile
} = $doOutputToFile;
118 } # _initializeOutput()
121 #--- HTML::TocInsertor::_deinitializeInsertorBatch() --------------------------
122 # function: Deinitialize insertor batch.
124 sub _deinitializeInsertorBatch
{
127 # Indicate ToC insertion has finished
128 $self->{_isTocInsertionPointPassed
} = 0;
129 # Write buffered output
130 $self->_writeBufferedOutput();
132 if ($self->{hti__Mode
} == MODE_DO_PROPAGATE
) {
134 # Deinitialize generator batch
135 $self->_deinitializeGeneratorBatch();
139 # Do general batch deinitialization
140 $self->_deinitializeBatch();
142 # Deinitialize output
143 $self->_deinitializeOutput();
144 # Indicate end of batch
145 $self->{hti__Mode
} = MODE_DO_NOTHING
;
146 # Reset batch variables
147 $self->_resetBatchVariables();
148 } # _deinitializeInsertorBatch()
151 #--- HTML::TocInsertor::_initializeInsertorBatch() ----------------------------
152 # function: Initialize insertor batch.
153 # args: - $aTocs: Reference to array of tocs.
154 # - $aOptions: optional options
156 sub _initializeInsertorBatch
{
158 my ($self, $aTocs, $aOptions) = @_;
159 # Add invocation options
160 $self->setOptions($aOptions);
161 # Option 'doGenerateToc' specified?
162 if (!defined($self->{options
}{'doGenerateToc'})) {
163 # No, options 'doGenerateToc' not specified;
164 # Default to 'doGenerateToc'
165 $self->{options
}{'doGenerateToc'} = 1;
168 if ($self->{options
}{'doGenerateToc'}) {
171 $self->{hti__Mode
} = MODE_DO_PROPAGATE
;
172 # Initialize generator batch
173 # NOTE: This method takes care of calling '_initializeBatch()'
174 $self->_initializeGeneratorBatch($aTocs);
179 $self->{hti__Mode
} = MODE_DO_INSERT
;
180 # Do general batch initialization
181 $self->_initializeBatch($aTocs);
184 $self->_initializeOutput();
185 # Parse ToC insertion points
186 $self->_parseTocInsertionPoints();
187 } # _initializeInsertorBatch()
190 #--- HTML::TocInsertor::_insert() ---------------------------------------------
191 # function: Insert ToC in string.
192 # args: - $aString: Reference to string to parse.
193 # note: Used internally.
197 my ($self, $aString) = @_;
199 if ($self->{options
}{'doGenerateToc'}) {
201 # Generate & insert ToC
202 $self->_generate($aString);
205 # No, just insert ToC
206 # Insert by parsing file
207 $self->parse($aString);
208 # Flush remaining buffered text
214 #--- HTML::TocInsertor::_insertIntoFile() -------------------------------------
215 # function: Do insert generated ToCs in file.
216 # args: - $aToc: (reference to array of) ToC object(s) to insert.
217 # - $aFile: (reference to array of) file(s) to parse for insertion
219 # - $aOptions: optional insertor options
220 # note: Used internally.
222 sub _insertIntoFile
{
224 my ($self, $aFile) = @_;
227 # Dereference array reference or make array of file specification
228 @files = (ref($aFile) =~ m/ARRAY/) ? @
$aFile : ($aFile);
230 foreach $file (@files) {
232 if ($self->{options
}{'doGenerateToc'}) {
234 # Generate and insert ToC
235 $self->_generateFromFile($file);
238 # No, just insert ToC
239 # Insert by parsing file
240 $self->parse_file($file);
243 } # _insertIntoFile()
246 #--- HTML::TocInsertor::_parseTocInsertionPoints() ----------------------------
247 # function: Parse ToC insertion point specifier.
249 sub _parseTocInsertionPoints
{
253 my ($tipPreposition, $tipToken, $toc, $tokenTipParser);
254 # Create parser for TIP tokens
255 $tokenTipParser = HTML
::_TokenTipParser
->new(
259 foreach $toc (@
{$self->{_tocs
}}) {
260 # Split TIP in preposition and token
261 ($tipPreposition, $tipToken) = split(
262 '\s+', $toc->{options
}{'insertionPoint'}, 2
266 ($tipPreposition ne TIP_PREPOSITION_REPLACE
) &&
267 ($tipPreposition ne TIP_PREPOSITION_BEFORE
) &&
268 ($tipPreposition ne TIP_PREPOSITION_AFTER
)
270 # No, unknown preposition;
271 # Use default preposition
272 $tipPreposition = TIP_PREPOSITION_AFTER
;
273 # Use entire 'insertionPoint' as token
274 $tipToken = $toc->{options
}{'insertionPoint'};
276 # Indicate current ToC to parser
277 $tokenTipParser->setToc($toc);
278 # Indicate current preposition to parser
279 $tokenTipParser->setPreposition($tipPreposition);
280 # Parse ToC Insertion Point
281 $tokenTipParser->parse($tipToken);
282 # Flush remaining buffered text
283 $tokenTipParser->eof();
285 } # _parseTocInsertionPoints()
288 #--- HTML::TocInsertor::_processTokenAsInsertionPoint() -----------------------
289 # function: Check for token being a ToC insertion point (Tip) token and
290 # process it accordingly.
291 # args: - $aTokenType: type of token: start, end, comment or text.
292 # - $aTokenId: token id of currently parsed token
293 # - $aTokenAttributes: attributes of currently parsed token
294 # - $aOrigText: complete token
295 # returns: 1 if successful -- token is processed as insertion point, 0
298 sub _processTokenAsInsertionPoint
{
300 my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aOrigText) = @_;
302 my ($i, $result, $tipToken, $tipTokenId, $tipTokens);
303 # Bias to token not functioning as a ToC insertion point (Tip) token
305 # Alias ToC insertion point (Tip) array of right type
306 $tipTokens = $self->{_tokensTip
}[$aTokenType];
307 # Loop through tipTokens
309 while ($i < scalar @
{$tipTokens}) {
311 $tipToken = $tipTokens->[$i];
312 $tipTokenId = $tipToken->[TIP_TOKEN_ID
];
313 # Id & attributes match?
315 ($aTokenId =~ m/$tipTokenId/) && (
316 HTML
::TocGenerator
::_doesHashContainHash
(
317 $aTokenAttributes, $tipToken->[TIP_INCLUDE_ATTRIBUTES
], 0
319 HTML
::TocGenerator
::_doesHashContainHash
(
320 $aTokenAttributes, $tipToken->[TIP_EXCLUDE_ATTRIBUTES
], 1
324 # Yes, id and attributes match;
325 # Process ToC insertion point
326 $self->_processTocInsertionPoint($tipToken);
327 # Indicate token functions as ToC insertion point
329 # Remove Tip token, automatically advancing to next token
330 splice(@
$tipTokens, $i, 1);
333 # No, tag doesn't match ToC insertion point
334 # Advance to next start token
338 # Token functions as ToC insertion point?
340 # Yes, token functions as ToC insertion point;
341 # Process insertion point(s)
342 $self->_processTocInsertionPoints($aOrigText);
346 } # _processTokenAsInsertionPoint()
349 #--- HTML::TocInsertor::toc() -------------------------------------------------
350 # function: Toc processing method. Add toc reference to scenario.
351 # args: - $aScenario: Scenario to add ToC reference to.
352 # - $aToc: Reference to ToC to insert.
353 # note: The ToC hasn't been build yet; only a reference to the ToC to be
358 my ($self, $aScenario, $aToc) = @_;
359 # Add toc to scenario
360 push(@
$aScenario, $aToc);
364 #--- HTML::TocInsertor::_processTocInsertionPoint() ----------------------------
365 # function: Process ToC insertion point.
366 # args: - $aTipToken: Reference to token array item which matches the ToC
369 sub _processTocInsertionPoint
{
371 my ($self, $aTipToken) = @_;
373 my ($tipToc, $tipPreposition);
376 $tipToc = $aTipToken->[TIP_TOC
];
377 $tipPreposition = $aTipToken->[TIP_PREPOSITION
];
380 # Replace token with ToC?
381 if ($tipPreposition eq TIP_PREPOSITION_REPLACE
) {
382 # Yes, replace token;
383 # Indicate ToC insertion point has been passed
384 $self->{_isTocInsertionPointPassed
} = 1;
385 # Add ToC reference to scenario reference by calling 'toc' method
386 $self->toc($self->{_scenarioAfterToken
}, $tipToc);
387 #push(@{$self->{_scenarioAfterToken}}, $tipTokenToc);
388 # Indicate token itself must not be output
389 $self->{_doOutputInsertionPointToken
} = 0;
392 # Output ToC before token?
393 if ($tipPreposition eq TIP_PREPOSITION_BEFORE
) {
394 # Yes, output ToC before token;
395 # Indicate ToC insertion point has been passed
396 $self->{_isTocInsertionPointPassed
} = 1;
397 # Add ToC reference to scenario reference by calling 'toc' method
398 $self->toc($self->{_scenarioBeforeToken
}, $tipToc);
399 #push(@{$self->{_scenarioBeforeToken}}, $tipTokenToc);
402 # Output ToC after token?
403 if ($tipPreposition eq TIP_PREPOSITION_AFTER
) {
404 # Yes, output ToC after token;
405 # Indicate ToC insertion point has been passed
406 $self->{_isTocInsertionPointPassed
} = 1;
407 # Add ToC reference to scenario reference by calling 'toc' method
408 $self->toc($self->{_scenarioAfterToken
}, $tipToc);
409 #push(@{$self->{_scenarioAfterToken}}, $tipTokenToc);
413 } # _processTocInsertionPoint()
416 #--- HTML::TocInsertor::_processTocInsertionPoints() --------------------------
417 # function: Process ToC insertion points
418 # args: - $aTokenText: Text of token which acts as insertion point for one
421 sub _processTocInsertionPoints
{
423 my ($self, $aTokenText) = @_;
425 my ($outputPrefix, $outputSuffix);
427 push(@
{$self->{_scenario
}}, @
{$self->{_scenarioBeforeToken
}});
429 if ($outputPrefix = $self->{_outputPrefix
}) {
430 push(@
{$self->{_scenario
}}, \
$outputPrefix);
431 $self->{_outputPrefix
} = "";
434 # Must insertion point token be output?
435 if ($self->{_doOutputInsertionPointToken
}) {
436 # Yes, output insertion point token;
437 push(@
{$self->{_scenario
}}, \
$aTokenText);
440 if ($outputSuffix = $self->{_outputSuffix
}) {
441 push(@
{$self->{_scenario
}}, \
$outputSuffix);
442 $self->{_outputSuffix
} = "";
445 push(@
{$self->{_scenario
}}, @
{$self->{_scenarioAfterToken
}});
446 # Add new act to scenario for output to come
448 push(@
{$self->{_scenario
}}, \
$output);
449 # Write output, processing possible '_outputSuffix'
450 #$self->_writeOrBufferOutput("");
451 # Reset helper scenario's
452 $self->{_scenarioBeforeToken
} = [];
453 $self->{_scenarioAfterToken
} = [];
454 # Reset bias value to output insertion point token
455 $self->{_doOutputInsertionPointToken
} = 1;
457 } # _processTocInsertionPoints()
460 #--- HTML::Toc::_resetBatchVariables() ----------------------------------------
461 # function: Reset batch variables.
463 sub _resetBatchVariables
{
466 $self->SUPER::_resetBatchVariables
();
467 # Array containing references to scalars. This array depicts the order
468 # in which output must be performed after the first ToC Insertion Point
470 $self->{_scenario
} = [];
472 $self->{_scenarioBeforeToken
} = [];
474 $self->{_scenarioAfterToken
} = [];
475 # Arrays containing start, end, comment, text & declaration tokens which
476 # must trigger the ToC insertion. Each array element may contain a
477 # reference to an array containing the following elements:
478 $self->{_tokensTip
} = [
479 [], # TT_TOKENTYPE_START
480 [], # TT_TOKENTYPE_END
481 [], # TT_TOKENTYPE_COMMENT
482 [], # TT_TOKENTYPE_TEXT
483 [] # TT_TOKENTYPE_DECLARATION
485 # 1 if ToC insertion point has been passed, 0 if not
486 $self->{_isTocInsertionPointPassed
} = 0;
488 $self->{outputBuffer
} = "";
489 # Trailing text after parsed token
490 $self->{_outputSuffix
} = "";
491 # Preceding text before parsed token
492 $self->{_outputPrefix
} = "";
493 } # _resetBatchVariables()
496 #--- HTML::TocInsertor::_writeBufferedOutput() --------------------------------
497 # function: Write buffered output to output device(s).
499 sub _writeBufferedOutput
{
504 # Must ToC be parsed?
505 if ($self->{options
}{'parseToc'}) {
506 # Yes, ToC must be parsed;
508 #$self->parse($self->{toc});
509 # Output tokens after ToC
510 #$self->_writeOrBufferOutput($self->{outputBuffer});
513 # No, ToC needn't be parsed;
515 foreach $scene (@
{$self->{_scenario
}}) {
516 # Is scene a reference to a scalar?
517 if (ref($scene) eq "SCALAR") {
518 # Yes, scene is a reference to a scalar;
520 $self->_writeOutput($$scene);
523 # No, scene must be reference to HTML::Toc;
525 $self->_writeOutput($scene->format());
529 } # _writeBufferedOutput()
532 #--- HTML::TocInsertor::_writeOrBufferOutput() --------------------------------
533 # function: Write processed HTML to output device(s).
534 # args: - aOutput: scalar to write
535 # note: If '_isTocInsertionPointPassed' text is buffered before being
536 # output because the ToC has to be generated before it can be output.
537 # Only after the entire data has been parsed, the ToC and the
538 # following text will be output.
540 sub _writeOrBufferOutput
{
542 my ($self, $aOutput) = @_;
544 # Add possible output prefix and suffix
545 $aOutput = $self->{_outputPrefix
} . $aOutput . $self->{_outputSuffix
};
546 # Clear output prefix and suffix
547 $self->{_outputPrefix
} = "";
548 $self->{_outputSuffix
} = "";
550 # Has ToC insertion point been passed?
551 if ($self->{_isTocInsertionPointPassed
}) {
552 # Yes, ToC insertion point has been passed;
553 # Buffer output; add output to last '_scenario' item
554 my $index = scalar(@
{$self->{_scenario
}}) - 1;
555 ${$self->{_scenario
}[$index]} .= $aOutput;
558 # No, ToC insertion point hasn't been passed;
560 $self->_writeOutput($aOutput);
562 } # _writeOrBufferOutput()
565 #--- HTML::TocInsertor::_writeOutput() ----------------------------------------
566 # function: Write processed HTML to output device(s).
567 # args: - aOutput: scalar to write
571 my ($self, $aOutput) = @_;
572 # Write output to scalar;
573 ${$self->{_output
}} .= $aOutput if (defined($self->{_output
}));
574 # Write output to output file
575 print $aOutput if ($self->{_doOutputToFile
})
579 #--- HTML::TocGenerator::anchorId() -------------------------------------------
580 # function: Anchor id processing method.
585 my ($self, $aAnchorId) = @_;
586 # Indicate id must be added to start tag
587 $self->{_doAddAnchorIdToStartTag
} = 1;
588 $self->{_anchorId
} = $aAnchorId;
592 #--- HTML::TocInsertor::anchorNameBegin() -------------------------------------
593 # function: Process anchor name begin, generated by HTML::TocGenerator.
594 # args: - $aAnchorNameBegin: Anchor name begin tag to output.
595 # - $aToc: Reference to ToC to which anchorname belongs.
597 sub anchorNameBegin
{
599 my ($self, $aAnchorNameBegin, $aToc) = @_;
600 # Is another anchorName active?
601 if (defined($self->{_activeAnchorName
})) {
602 # Yes, another anchorName is active;
606 HTML
::TocGenerator
::WARNING_NESTED_ANCHOR_PS_WITHIN_PS
,
607 [$aAnchorNameBegin, $self->{_activeAnchorName
}]
610 # Store anchor name as output prefix
611 $self->{_outputPrefix
} = $aAnchorNameBegin;
612 # Indicate active anchor name
613 $self->{_activeAnchorName
} = $aAnchorNameBegin;
614 # Indicate anchor name end must be output
615 $self->{_doOutputAnchorNameEnd
} = 1;
616 } # anchorNameBegin()
619 #--- HTML::TocInsertor::anchorNameEnd() ---------------------------------------
620 # function: Process anchor name end, generated by HTML::TocGenerator.
621 # args: - $aAnchorNameEnd: Anchor name end tag to output.
622 # - $aToc: Reference to ToC to which anchorname belongs.
626 my ($self, $aAnchorNameEnd) = @_;
627 # Store anchor name as output prefix
628 $self->{_outputSuffix
} .= $aAnchorNameEnd;
629 # Indicate deactive anchor name
630 $self->{_activeAnchorName
} = undef;
634 #--- HTML::TocInsertor::comment() ---------------------------------------------
635 # function: Process comment.
636 # args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
640 my ($self, $aComment) = @_;
642 my ($tocInsertionPointToken, $doOutput, $origText);
643 # Allow ancestor to process the comment tag
644 $self->SUPER::comment
($aComment);
645 # Assemble original comment
646 $origText = "<!--$aComment-->";
647 # Must ToCs be inserted?
648 if ($self->{hti__Mode
} & MODE_DO_INSERT
) {
649 # Yes, ToCs must be inserted;
650 # Processing comment as ToC insertion point is successful?
651 if (! $self->_processTokenAsInsertionPoint(
652 HTML
::TocGenerator
::TT_TOKENTYPE_COMMENT
, $aComment, undef, $origText
654 # No, comment isn't a ToC insertion point;
655 # Output comment normally
656 $self->_writeOrBufferOutput($origText);
662 #--- HTML::TocInsertor::declaration() -----------------------------------------
663 # function: This function is called every time a declaration is encountered
668 my ($self, $aDeclaration) = @_;
669 # Allow ancestor to process the declaration tag
670 $self->SUPER::declaration
($aDeclaration);
671 # Must ToCs be inserted?
672 if ($self->{hti__Mode
} & MODE_DO_INSERT
) {
673 # Yes, ToCs must be inserted;
674 # Processing declaration as ToC insertion point is successful?
675 if (! $self->_processTokenAsInsertionPoint(
676 HTML
::TocGenerator
::TT_TOKENTYPE_DECLARATION
, $aDeclaration, undef,
679 # No, declaration isn't a ToC insertion point;
680 # Output declaration normally
681 $self->_writeOrBufferOutput("<!$aDeclaration>");
687 #--- HTML::TocInsertor::end() -------------------------------------------------
688 # function: This function is called every time a closing tag is encountered
690 # args: - $aTag: tag name (in lower case).
694 my ($self, $aTag, $aOrigText) = @_;
695 # Allow ancestor to process the end tag
696 $self->SUPER::end
($aTag, $aOrigText);
697 # Must ToCs be inserted?
698 if ($self->{hti__Mode
} & MODE_DO_INSERT
) {
699 # Yes, ToCs must be inserted;
700 # Processing end tag as ToC insertion point is successful?
701 if (! $self->_processTokenAsInsertionPoint(
702 HTML
::TocGenerator
::TT_TOKENTYPE_END
, $aTag, undef, $aOrigText
704 # No, end tag isn't a ToC insertion point;
705 # Output end tag normally
706 $self->_writeOrBufferOutput($aOrigText);
712 #--- HTML::TocInsertor::insert() ----------------------------------------------
713 # function: Insert ToC in string.
714 # args: - $aToc: (reference to array of) ToC object to insert
715 # - $aString: string to insert ToC in
716 # - $aOptions: hash reference with optional insertor options
720 my ($self, $aToc, $aString, $aOptions) = @_;
721 # Initialize TocInsertor batch
722 $self->_initializeInsertorBatch($aToc, $aOptions);
724 $self->_insert($aString);
725 # Deinitialize TocInsertor batch
726 $self->_deinitializeInsertorBatch();
730 #--- HTML::TocInsertor::insertIntoFile() --------------------------------------
731 # function: Insert ToCs in file.
732 # args: - $aToc: (reference to array of) ToC object(s) to insert.
733 # - $aFile: (reference to array of) file(s) to parse for insertion
735 # - $aOptions: optional insertor options
739 my ($self, $aToc, $aFile, $aOptions) = @_;
740 # Initialize TocInsertor batch
741 $self->_initializeInsertorBatch($aToc, $aOptions);
742 # Do insert ToCs into file
743 $self->_insertIntoFile($aFile);
744 # Deinitialize TocInsertor batch
745 $self->_deinitializeInsertorBatch();
749 #--- HTML::TocInsertor::number() ----------------------------------------------
750 # function: Process heading number generated by HTML::Toc.
755 my ($self, $aNumber) = @_;
756 # Store heading number as output suffix
757 $self->{_outputSuffix
} .= $aNumber;
761 #--- HTML::TocInsertor::propagateFile() ---------------------------------------
762 # function: Propagate ToC; generate & insert ToC, using file as input.
763 # args: - $aToc: (reference to array of) ToC object to insert
764 # - $aFile: (reference to array of) file to parse for insertion
766 # - $aOptions: optional insertor options
770 my ($self, $aToc, $aFile, $aOptions) = @_;
773 # Initialize TocInsertor batch
774 $self->_initializeInsertorBatch($aToc, $aOptions);
775 # Dereference array reference or make array of file specification
776 @files = (ref($aFile) =~ m/ARRAY/) ? @
$aFile : ($aFile);
778 foreach $file (@files) {
779 # Generate and insert ToC
780 $self->_generateFromFile($file);
782 # Deinitialize TocInsertor batch
783 $self->_deinitializeInsertorBatch();
787 #--- HTML::TocInsertor::start() -----------------------------------------------
788 # function: This function is called every time an opening tag is encountered.
789 # args: - $aTag: tag name (in lower case).
790 # - $aAttr: reference to hash containing all tag attributes (in lower
792 # - $aAttrSeq: reference to array containing all tag attributes (in
793 # lower case) in the original order
794 # - $aOrigText: the original HTML text
798 my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
800 my ($doOutput, $i, $tocToken, $tag, $anchorId);
801 # Let ancestor process the start tag
802 $self->SUPER::start
($aTag, $aAttr, $aAttrSeq, $aOrigText);
803 # Must ToC be inserted?
804 if ($self->{hti__Mode
} & MODE_DO_INSERT
) {
805 # Yes, ToC must be inserted;
806 # Processing start tag as ToC insertion point is successful?
807 if (! $self->_processTokenAsInsertionPoint(
808 HTML
::TocGenerator
::TT_TOKENTYPE_START
, $aTag, $aAttr, $aOrigText
810 # No, start tag isn't a ToC insertion point;
812 if ($self->{_doAddAnchorIdToStartTag
}) {
813 # Yes, anchor id must be added;
815 $self->{_doAddAnchorIdToStartTag
} = 0;
817 $anchorId = $self->{_anchorId
};
818 # Attribute 'id' already exists?
819 if (defined($aAttr->{id
})) {
820 # Yes, attribute 'id' already exists;
822 print STDERR
"WARNING: Overwriting existing id attribute '" .
823 $aAttr->{id
} . "' of tag $aOrigText\n";
825 # Add anchor id to start tag
826 $aOrigText =~ s/(id)=\S*([\s>])/$1=$anchorId$2/i;
829 # No, attribute 'id' doesn't exist;
830 # Add anchor id to start tag
831 $aOrigText =~ s/>/ id=$anchorId>/;
834 # Output start tag normally
835 $self->_writeOrBufferOutput($aOrigText);
841 #--- HTML::TocInsertor::text() ------------------------------------------------
842 # function: This function is called every time plain text is encountered.
843 # args: - @_: array containing data.
847 my ($self, $aText) = @_;
848 # Let ancestor process the text
849 $self->SUPER::text
($aText);
850 # Must ToC be inserted?
851 if ($self->{hti__Mode
} & MODE_DO_INSERT
) {
852 # Yes, ToC must be inserted;
853 # Processing text as ToC insertion point is successful?
854 if (! $self->_processTokenAsInsertionPoint(
855 HTML
::TocGenerator
::TT_TOKENTYPE_TEXT
, $aText, undef, $aText
857 # No, text isn't a ToC insertion point;
858 # Output text normally
859 $self->_writeOrBufferOutput($aText);
867 #=== HTML::_TokenTipParser ====================================================
868 # function: Parse 'TIP tokens'. 'TIP tokens' mark HTML code which is to be
869 # used as the ToC Insertion Point.
870 # note: Used internally.
872 package HTML
::_TokenTipParser
;
878 @ISA = qw(HTML::_TokenTocParser);
885 #--- HTML::_TokenTipParser::new() ---------------------------------------------
886 # function: Constructor
890 my ($aType, $aTokenArray) = @_;
892 my $self = $aType->SUPER::new
;
893 # Reference token array
894 $self->{tokens
} = $aTokenArray;
895 # Reference to last added token
896 $self->{_lastAddedToken
} = undef;
897 $self->{_lastAddedTokenType
} = undef;
903 #--- HTML::_TokenTipParser::_processAttributes() ------------------------------
904 # function: Process attributes.
905 # args: - $aAttributes: Attributes to parse.
907 sub _processAttributes
{
909 my ($self, $aAttributes) = @_;
911 my (%includeAttributes, %excludeAttributes);
914 $self->_parseAttributes(
915 $aAttributes, \
%includeAttributes, \
%excludeAttributes
917 # Include attributes are specified?
918 if (keys(%includeAttributes) > 0) {
919 # Yes, include attributes are specified;
920 # Store include attributes
921 @
${$self->{_lastAddedToken
}}[
922 HTML
::TocInsertor
::TIP_INCLUDE_ATTRIBUTES
923 ] = \
%includeAttributes;
925 # Exclude attributes are specified?
926 if (keys(%excludeAttributes) > 0) {
927 # Yes, exclude attributes are specified;
928 # Store exclude attributes
929 @
${$self->{_lastAddedToken
}}[
930 HTML
::TocInsertor
::TIP_EXCLUDE_ATTRIBUTES
931 ] = \
%excludeAttributes;
933 } # _processAttributes()
936 #--- HTML::_TokenTipParser::_processToken() -----------------------------------
937 # function: Process token.
938 # args: - $aTokenType: Type of token to process.
939 # - $aTag: Tag of token.
943 my ($self, $aTokenType, $aTag) = @_;
945 my ($tokenArray, $index);
946 # Push element on array of update tokens
947 $index = push(@
{$self->{tokens
}[$aTokenType]}, []) - 1;
948 # Alias token array to add element to
949 $tokenArray = $self->{tokens
}[$aTokenType];
950 # Indicate last updated token array element
951 $self->{_lastAddedTokenType
} = $aTokenType;
952 $self->{_lastAddedToken
} = \
$$tokenArray[$index];
954 $$tokenArray[$index][HTML
::TocInsertor
::TIP_TOC
] = $self->{_toc
};
955 $$tokenArray[$index][HTML
::TocInsertor
::TIP_TOKEN_ID
] = $aTag;
956 $$tokenArray[$index][HTML
::TocInsertor
::TIP_PREPOSITION
] =
957 $self->{_preposition
};
961 #--- HTML::_TokenTipParser::comment() -----------------------------------------
962 # function: Process comment.
963 # args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
967 my ($self, $aComment) = @_;
969 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_COMMENT
, $aComment);
973 #--- HTML::_TokenTipParser::declaration() --------------------------------
974 # function: This function is called every time a markup declaration is
975 # encountered by HTML::Parser.
976 # args: - $aDeclaration: Markup declaration.
980 my ($self, $aDeclaration) = @_;
982 $self->_processToken(
983 HTML
::TocGenerator
::TT_TOKENTYPE_DECLARATION
, $aDeclaration
988 #--- HTML::_TokenTipParser::end() ----------------------------------------
989 # function: This function is called every time a closing tag is encountered
991 # args: - $aTag: tag name (in lower case).
995 my ($self, $aTag, $aOrigText) = @_;
997 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_END
, $aTag);
1001 #--- HTML::_TokenTipParser->setPreposition() ----------------------------------
1002 # function: Set current preposition.
1004 sub setPreposition
{
1006 my ($self, $aPreposition) = @_;
1008 $self->{_preposition
} = $aPreposition;
1009 } # setPreposition()
1012 #--- HTML::_TokenTipParser->setToc() ------------------------------------------
1013 # function: Set current ToC.
1017 my ($self, $aToc) = @_;
1019 $self->{_toc
} = $aToc;
1023 #--- HTML::_TokenTipParser::start() --------------------------------------
1024 # function: This function is called every time an opening tag is encountered.
1025 # args: - $aTag: tag name (in lower case).
1026 # - $aAttr: reference to hash containing all tag attributes (in lower
1028 # - $aAttrSeq: reference to array containing all attribute keys (in
1029 # lower case) in the original order
1030 # - $aOrigText: the original HTML text
1034 my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1036 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_START
, $aTag);
1037 # Process attributes
1038 $self->_processAttributes($aAttr);
1042 #--- HTML::_TokenTipParser::text() ---------------------------------------
1043 # function: This function is called every time plain text is encountered.
1044 # args: - @_: array containing data.
1048 my ($self, $aText) = @_;
1049 # Was token already created and is last added token of type 'text'?
1051 defined($self->{_lastAddedToken
}) &&
1052 $self->{_lastAddedTokenType
} == HTML
::TocGenerator
::TT_TOKENTYPE_TEXT
1054 # Yes, token is already created;
1055 # Add tag to existing token
1056 @
${$self->{_lastAddedToken
}}[HTML
::TocGenerator
::TT_TAG_BEGIN
] .= $aText;
1059 # No, token isn't created;
1061 $self->_processToken(HTML
::TocGenerator
::TT_TOKENTYPE_TEXT
, $aText);