| #--- TocInsertor.pm ----------------------------------------------------------- |
| # function: Insert Table of Contents HTML::Toc, generated by |
| # HTML::TocGenerator. |
| # note: - The term 'propagate' is used as a shortcut for the process of |
| # both generating and inserting a ToC at the same time. |
| # - 'TIP' is an abbreviation of 'Toc Insertion Point'. |
| |
| |
| package HTML::TocInsertor; |
| |
| |
| use strict; |
| use FileHandle; |
| use HTML::TocGenerator; |
| |
| |
| BEGIN { |
| use vars qw(@ISA $VERSION); |
| |
| $VERSION = '0.91'; |
| |
| @ISA = qw(HTML::TocGenerator); |
| } |
| |
| # TocInsertionPoint (TIP) constants |
| |
| use constant TIP_PREPOSITION_REPLACE => 'replace'; |
| use constant TIP_PREPOSITION_BEFORE => 'before'; |
| use constant TIP_PREPOSITION_AFTER => 'after'; |
| |
| use constant TIP_TOKEN_ID => 0; |
| use constant TIP_PREPOSITION => 1; |
| use constant TIP_INCLUDE_ATTRIBUTES => 2; |
| use constant TIP_EXCLUDE_ATTRIBUTES => 3; |
| use constant TIP_TOC => 4; |
| |
| use constant MODE_DO_NOTHING => 0; # 0b00 |
| use constant MODE_DO_INSERT => 1; # 0b01 |
| use constant MODE_DO_PROPAGATE => 3; # 0b11 |
| |
| END {} |
| |
| |
| #--- HTML::TocInsertor::new() ------------------------------------------------- |
| # function: Constructor. |
| |
| sub new { |
| # Get arguments |
| my ($aType) = @_; |
| my $self = $aType->SUPER::new; |
| # TRUE if insertion point token must be output, FALSE if not |
| $self->{_doOutputInsertionPointToken} = 1; |
| # Reset batch variables |
| $self->_resetBatchVariables; |
| # Bias to not insert ToC |
| $self->{hti__Mode} = MODE_DO_NOTHING; |
| |
| # TODO: Initialize output |
| |
| return $self; |
| } # new() |
| |
| |
| #--- HTML::TocInsertor::_deinitializeOutput() --------------------------------- |
| # function: Deinitialize output. |
| |
| sub _deinitializeOutput { |
| # Get arguments |
| my ($self) = @_; |
| # Filehandle is defined? |
| if (defined($self->{_outputFileHandle})) { |
| # Yes, filehandle is defined; |
| # Restore selected filehandle |
| select($self->{_oldFileHandle}); |
| # Undefine filehandle, closing it automatically |
| undef $self->{_outputFileHandle}; |
| } |
| } # _deinitializeOutput() |
| |
| |
| #--- HTML::TocInsertor::_initializeOutput() ----------------------------------- |
| # function: Initialize output. |
| |
| sub _initializeOutput { |
| # Get arguments |
| my ($self) = @_; |
| # Bias to write to outputfile |
| my $doOutputToFile = 1; |
| |
| # Is output specified? |
| if (defined($self->{options}{'output'})) { |
| # Yes, output is specified; |
| # Indicate to not output to outputfile |
| $doOutputToFile = 0; |
| # Alias output reference |
| $self->{_output} = $self->{options}{'output'}; |
| # Clear output |
| ${$self->{_output}} = ""; |
| } |
| |
| # Is output file specified? |
| if (defined($self->{options}{'outputFile'})) { |
| # Yes, output file is specified; |
| # Indicate to output to outputfile |
| $doOutputToFile = 1; |
| # Open file |
| $self->{_outputFileHandle} = |
| new FileHandle ">" . $self->{options}{'outputFile'}; |
| |
| # Backup currently selected filehandle |
| $self->{_oldFileHandle} = select; |
| # Set new default filehandle |
| select($self->{_outputFileHandle}); |
| } |
| |
| # Alias output-to-file indicator |
| $self->{_doOutputToFile} = $doOutputToFile; |
| } # _initializeOutput() |
| |
| |
| #--- HTML::TocInsertor::_deinitializeInsertorBatch() -------------------------- |
| # function: Deinitialize insertor batch. |
| |
| sub _deinitializeInsertorBatch { |
| # Get arguments |
| my ($self) = @_; |
| # Indicate ToC insertion has finished |
| $self->{_isTocInsertionPointPassed} = 0; |
| # Write buffered output |
| $self->_writeBufferedOutput(); |
| # Propagate? |
| if ($self->{hti__Mode} == MODE_DO_PROPAGATE) { |
| # Yes, propagate; |
| # Deinitialize generator batch |
| $self->_deinitializeGeneratorBatch(); |
| } |
| else { |
| # No, insert only; |
| # Do general batch deinitialization |
| $self->_deinitializeBatch(); |
| } |
| # Deinitialize output |
| $self->_deinitializeOutput(); |
| # Indicate end of batch |
| $self->{hti__Mode} = MODE_DO_NOTHING; |
| # Reset batch variables |
| $self->_resetBatchVariables(); |
| } # _deinitializeInsertorBatch() |
| |
| |
| #--- HTML::TocInsertor::_initializeInsertorBatch() ---------------------------- |
| # function: Initialize insertor batch. |
| # args: - $aTocs: Reference to array of tocs. |
| # - $aOptions: optional options |
| |
| sub _initializeInsertorBatch { |
| # Get arguments |
| my ($self, $aTocs, $aOptions) = @_; |
| # Add invocation options |
| $self->setOptions($aOptions); |
| # Option 'doGenerateToc' specified? |
| if (!defined($self->{options}{'doGenerateToc'})) { |
| # No, options 'doGenerateToc' not specified; |
| # Default to 'doGenerateToc' |
| $self->{options}{'doGenerateToc'} = 1; |
| } |
| # Propagate? |
| if ($self->{options}{'doGenerateToc'}) { |
| # Yes, propagate; |
| # Indicate mode |
| $self->{hti__Mode} = MODE_DO_PROPAGATE; |
| # Initialize generator batch |
| # NOTE: This method takes care of calling '_initializeBatch()' |
| $self->_initializeGeneratorBatch($aTocs); |
| } |
| else { |
| # No, insert; |
| # Indicate mode |
| $self->{hti__Mode} = MODE_DO_INSERT; |
| # Do general batch initialization |
| $self->_initializeBatch($aTocs); |
| } |
| # Initialize output |
| $self->_initializeOutput(); |
| # Parse ToC insertion points |
| $self->_parseTocInsertionPoints(); |
| } # _initializeInsertorBatch() |
| |
| |
| #--- HTML::TocInsertor::_insert() --------------------------------------------- |
| # function: Insert ToC in string. |
| # args: - $aString: Reference to string to parse. |
| # note: Used internally. |
| |
| sub _insert { |
| # Get arguments |
| my ($self, $aString) = @_; |
| # Propagate? |
| if ($self->{options}{'doGenerateToc'}) { |
| # Yes, propagate; |
| # Generate & insert ToC |
| $self->_generate($aString); |
| } |
| else { |
| # No, just insert ToC |
| # Insert by parsing file |
| $self->parse($aString); |
| # Flush remaining buffered text |
| $self->eof(); |
| } |
| } # _insert() |
| |
| |
| #--- HTML::TocInsertor::_insertIntoFile() ------------------------------------- |
| # function: Do insert generated ToCs in file. |
| # args: - $aToc: (reference to array of) ToC object(s) to insert. |
| # - $aFile: (reference to array of) file(s) to parse for insertion |
| # points. |
| # - $aOptions: optional insertor options |
| # note: Used internally. |
| |
| sub _insertIntoFile { |
| # Get arguments |
| my ($self, $aFile) = @_; |
| # Local variables; |
| my ($file, @files); |
| # Dereference array reference or make array of file specification |
| @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile); |
| # Loop through files |
| foreach $file (@files) { |
| # Propagate? |
| if ($self->{options}{'doGenerateToc'}) { |
| # Yes, propagate; |
| # Generate and insert ToC |
| $self->_generateFromFile($file); |
| } |
| else { |
| # No, just insert ToC |
| # Insert by parsing file |
| $self->parse_file($file); |
| } |
| } |
| } # _insertIntoFile() |
| |
| |
| #--- HTML::TocInsertor::_parseTocInsertionPoints() ---------------------------- |
| # function: Parse ToC insertion point specifier. |
| |
| sub _parseTocInsertionPoints { |
| # Get arguments |
| my ($self) = @_; |
| # Local variables |
| my ($tipPreposition, $tipToken, $toc, $tokenTipParser); |
| # Create parser for TIP tokens |
| $tokenTipParser = HTML::_TokenTipParser->new( |
| $self->{_tokensTip} |
| ); |
| # Loop through ToCs |
| foreach $toc (@{$self->{_tocs}}) { |
| # Split TIP in preposition and token |
| ($tipPreposition, $tipToken) = split( |
| '\s+', $toc->{options}{'insertionPoint'}, 2 |
| ); |
| # Known preposition? |
| if ( |
| ($tipPreposition ne TIP_PREPOSITION_REPLACE) && |
| ($tipPreposition ne TIP_PREPOSITION_BEFORE) && |
| ($tipPreposition ne TIP_PREPOSITION_AFTER) |
| ) { |
| # No, unknown preposition; |
| # Use default preposition |
| $tipPreposition = TIP_PREPOSITION_AFTER; |
| # Use entire 'insertionPoint' as token |
| $tipToken = $toc->{options}{'insertionPoint'}; |
| } |
| # Indicate current ToC to parser |
| $tokenTipParser->setToc($toc); |
| # Indicate current preposition to parser |
| $tokenTipParser->setPreposition($tipPreposition); |
| # Parse ToC Insertion Point |
| $tokenTipParser->parse($tipToken); |
| # Flush remaining buffered text |
| $tokenTipParser->eof(); |
| } |
| } # _parseTocInsertionPoints() |
| |
| |
| #--- HTML::TocInsertor::_processTokenAsInsertionPoint() ----------------------- |
| # function: Check for token being a ToC insertion point (Tip) token and |
| # process it accordingly. |
| # args: - $aTokenType: type of token: start, end, comment or text. |
| # - $aTokenId: token id of currently parsed token |
| # - $aTokenAttributes: attributes of currently parsed token |
| # - $aOrigText: complete token |
| # returns: 1 if successful -- token is processed as insertion point, 0 |
| # if not. |
| |
| sub _processTokenAsInsertionPoint { |
| # Get arguments |
| my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aOrigText) = @_; |
| # Local variables |
| my ($i, $result, $tipToken, $tipTokenId, $tipTokens); |
| # Bias to token not functioning as a ToC insertion point (Tip) token |
| $result = 0; |
| # Alias ToC insertion point (Tip) array of right type |
| $tipTokens = $self->{_tokensTip}[$aTokenType]; |
| # Loop through tipTokens |
| $i = 0; |
| while ($i < scalar @{$tipTokens}) { |
| # Aliases |
| $tipToken = $tipTokens->[$i]; |
| $tipTokenId = $tipToken->[TIP_TOKEN_ID]; |
| # Id & attributes match? |
| if ( |
| ($aTokenId =~ m/$tipTokenId/) && ( |
| HTML::TocGenerator::_doesHashContainHash( |
| $aTokenAttributes, $tipToken->[TIP_INCLUDE_ATTRIBUTES], 0 |
| ) && |
| HTML::TocGenerator::_doesHashContainHash( |
| $aTokenAttributes, $tipToken->[TIP_EXCLUDE_ATTRIBUTES], 1 |
| ) |
| ) |
| ) { |
| # Yes, id and attributes match; |
| # Process ToC insertion point |
| $self->_processTocInsertionPoint($tipToken); |
| # Indicate token functions as ToC insertion point |
| $result = 1; |
| # Remove Tip token, automatically advancing to next token |
| splice(@$tipTokens, $i, 1); |
| } |
| else { |
| # No, tag doesn't match ToC insertion point |
| # Advance to next start token |
| $i++; |
| } |
| } |
| # Token functions as ToC insertion point? |
| if ($result) { |
| # Yes, token functions as ToC insertion point; |
| # Process insertion point(s) |
| $self->_processTocInsertionPoints($aOrigText); |
| } |
| # Return value |
| return $result; |
| } # _processTokenAsInsertionPoint() |
| |
| |
| #--- HTML::TocInsertor::toc() ------------------------------------------------- |
| # function: Toc processing method. Add toc reference to scenario. |
| # args: - $aScenario: Scenario to add ToC reference to. |
| # - $aToc: Reference to ToC to insert. |
| # note: The ToC hasn't been build yet; only a reference to the ToC to be |
| # build is inserted. |
| |
| sub toc { |
| # Get arguments |
| my ($self, $aScenario, $aToc) = @_; |
| # Add toc to scenario |
| push(@$aScenario, $aToc); |
| } # toc() |
| |
| |
| #--- HTML::TocInsertor::_processTocInsertionPoint() ---------------------------- |
| # function: Process ToC insertion point. |
| # args: - $aTipToken: Reference to token array item which matches the ToC |
| # insertion point. |
| |
| sub _processTocInsertionPoint { |
| # Get arguments |
| my ($self, $aTipToken) = @_; |
| # Local variables |
| my ($tipToc, $tipPreposition); |
| |
| # Aliases |
| $tipToc = $aTipToken->[TIP_TOC]; |
| $tipPreposition = $aTipToken->[TIP_PREPOSITION]; |
| |
| SWITCH: { |
| # Replace token with ToC? |
| if ($tipPreposition eq TIP_PREPOSITION_REPLACE) { |
| # Yes, replace token; |
| # Indicate ToC insertion point has been passed |
| $self->{_isTocInsertionPointPassed} = 1; |
| # Add ToC reference to scenario reference by calling 'toc' method |
| $self->toc($self->{_scenarioAfterToken}, $tipToc); |
| #push(@{$self->{_scenarioAfterToken}}, $tipTokenToc); |
| # Indicate token itself must not be output |
| $self->{_doOutputInsertionPointToken} = 0; |
| last SWITCH; |
| } |
| # Output ToC before token? |
| if ($tipPreposition eq TIP_PREPOSITION_BEFORE) { |
| # Yes, output ToC before token; |
| # Indicate ToC insertion point has been passed |
| $self->{_isTocInsertionPointPassed} = 1; |
| # Add ToC reference to scenario reference by calling 'toc' method |
| $self->toc($self->{_scenarioBeforeToken}, $tipToc); |
| #push(@{$self->{_scenarioBeforeToken}}, $tipTokenToc); |
| last SWITCH; |
| } |
| # Output ToC after token? |
| if ($tipPreposition eq TIP_PREPOSITION_AFTER) { |
| # Yes, output ToC after token; |
| # Indicate ToC insertion point has been passed |
| $self->{_isTocInsertionPointPassed} = 1; |
| # Add ToC reference to scenario reference by calling 'toc' method |
| $self->toc($self->{_scenarioAfterToken}, $tipToc); |
| #push(@{$self->{_scenarioAfterToken}}, $tipTokenToc); |
| last SWITCH; |
| } |
| } |
| } # _processTocInsertionPoint() |
| |
| |
| #--- HTML::TocInsertor::_processTocInsertionPoints() -------------------------- |
| # function: Process ToC insertion points |
| # args: - $aTokenText: Text of token which acts as insertion point for one |
| # or multiple ToCs. |
| |
| sub _processTocInsertionPoints { |
| # Get arguments |
| my ($self, $aTokenText) = @_; |
| # Local variables |
| my ($outputPrefix, $outputSuffix); |
| # Extend scenario |
| push(@{$self->{_scenario}}, @{$self->{_scenarioBeforeToken}}); |
| |
| if ($outputPrefix = $self->{_outputPrefix}) { |
| push(@{$self->{_scenario}}, \$outputPrefix); |
| $self->{_outputPrefix} = ""; |
| } |
| |
| # Must insertion point token be output? |
| if ($self->{_doOutputInsertionPointToken}) { |
| # Yes, output insertion point token; |
| push(@{$self->{_scenario}}, \$aTokenText); |
| } |
| |
| if ($outputSuffix = $self->{_outputSuffix}) { |
| push(@{$self->{_scenario}}, \$outputSuffix); |
| $self->{_outputSuffix} = ""; |
| } |
| |
| push(@{$self->{_scenario}}, @{$self->{_scenarioAfterToken}}); |
| # Add new act to scenario for output to come |
| my $output = ""; |
| push(@{$self->{_scenario}}, \$output); |
| # Write output, processing possible '_outputSuffix' |
| #$self->_writeOrBufferOutput(""); |
| # Reset helper scenario's |
| $self->{_scenarioBeforeToken} = []; |
| $self->{_scenarioAfterToken} = []; |
| # Reset bias value to output insertion point token |
| $self->{_doOutputInsertionPointToken} = 1; |
| |
| } # _processTocInsertionPoints() |
| |
| |
| #--- HTML::Toc::_resetBatchVariables() ---------------------------------------- |
| # function: Reset batch variables. |
| |
| sub _resetBatchVariables { |
| my ($self) = @_; |
| # Call ancestor |
| $self->SUPER::_resetBatchVariables(); |
| # Array containing references to scalars. This array depicts the order |
| # in which output must be performed after the first ToC Insertion Point |
| # has been passed. |
| $self->{_scenario} = []; |
| # Helper scenario |
| $self->{_scenarioBeforeToken} = []; |
| # Helper scenario |
| $self->{_scenarioAfterToken} = []; |
| # Arrays containing start, end, comment, text & declaration tokens which |
| # must trigger the ToC insertion. Each array element may contain a |
| # reference to an array containing the following elements: |
| $self->{_tokensTip} = [ |
| [], # TT_TOKENTYPE_START |
| [], # TT_TOKENTYPE_END |
| [], # TT_TOKENTYPE_COMMENT |
| [], # TT_TOKENTYPE_TEXT |
| [] # TT_TOKENTYPE_DECLARATION |
| ]; |
| # 1 if ToC insertion point has been passed, 0 if not |
| $self->{_isTocInsertionPointPassed} = 0; |
| # Tokens after ToC |
| $self->{outputBuffer} = ""; |
| # Trailing text after parsed token |
| $self->{_outputSuffix} = ""; |
| # Preceding text before parsed token |
| $self->{_outputPrefix} = ""; |
| } # _resetBatchVariables() |
| |
| |
| #--- HTML::TocInsertor::_writeBufferedOutput() -------------------------------- |
| # function: Write buffered output to output device(s). |
| |
| sub _writeBufferedOutput { |
| # Get arguments |
| my ($self) = @_; |
| # Local variables |
| my ($scene); |
| # Must ToC be parsed? |
| if ($self->{options}{'parseToc'}) { |
| # Yes, ToC must be parsed; |
| # Parse ToC |
| #$self->parse($self->{toc}); |
| # Output tokens after ToC |
| #$self->_writeOrBufferOutput($self->{outputBuffer}); |
| } |
| else { |
| # No, ToC needn't be parsed; |
| # Output scenario |
| foreach $scene (@{$self->{_scenario}}) { |
| # Is scene a reference to a scalar? |
| if (ref($scene) eq "SCALAR") { |
| # Yes, scene is a reference to a scalar; |
| # Output scene |
| $self->_writeOutput($$scene); |
| } |
| else { |
| # No, scene must be reference to HTML::Toc; |
| # Output toc |
| $self->_writeOutput($scene->format()); |
| } |
| } |
| } |
| } # _writeBufferedOutput() |
| |
| |
| #--- HTML::TocInsertor::_writeOrBufferOutput() -------------------------------- |
| # function: Write processed HTML to output device(s). |
| # args: - aOutput: scalar to write |
| # note: If '_isTocInsertionPointPassed' text is buffered before being |
| # output because the ToC has to be generated before it can be output. |
| # Only after the entire data has been parsed, the ToC and the |
| # following text will be output. |
| |
| sub _writeOrBufferOutput { |
| # Get arguments |
| my ($self, $aOutput) = @_; |
| |
| # Add possible output prefix and suffix |
| $aOutput = $self->{_outputPrefix} . $aOutput . $self->{_outputSuffix}; |
| # Clear output prefix and suffix |
| $self->{_outputPrefix} = ""; |
| $self->{_outputSuffix} = ""; |
| |
| # Has ToC insertion point been passed? |
| if ($self->{_isTocInsertionPointPassed}) { |
| # Yes, ToC insertion point has been passed; |
| # Buffer output; add output to last '_scenario' item |
| my $index = scalar(@{$self->{_scenario}}) - 1; |
| ${$self->{_scenario}[$index]} .= $aOutput; |
| } |
| else { |
| # No, ToC insertion point hasn't been passed; |
| # Write output |
| $self->_writeOutput($aOutput); |
| } |
| } # _writeOrBufferOutput() |
| |
| |
| #--- HTML::TocInsertor::_writeOutput() ---------------------------------------- |
| # function: Write processed HTML to output device(s). |
| # args: - aOutput: scalar to write |
| |
| sub _writeOutput { |
| # Get arguments |
| my ($self, $aOutput) = @_; |
| # Write output to scalar; |
| ${$self->{_output}} .= $aOutput if (defined($self->{_output})); |
| # Write output to output file |
| print $aOutput if ($self->{_doOutputToFile}) |
| } # _writeOutput() |
| |
| |
| #--- HTML::TocGenerator::anchorId() ------------------------------------------- |
| # function: Anchor id processing method. |
| # args: - $aAnchorId |
| |
| sub anchorId { |
| # Get arguments |
| my ($self, $aAnchorId) = @_; |
| # Indicate id must be added to start tag |
| $self->{_doAddAnchorIdToStartTag} = 1; |
| $self->{_anchorId} = $aAnchorId; |
| } # anchorId() |
| |
| |
| #--- HTML::TocInsertor::anchorNameBegin() ------------------------------------- |
| # function: Process anchor name begin, generated by HTML::TocGenerator. |
| # args: - $aAnchorNameBegin: Anchor name begin tag to output. |
| # - $aToc: Reference to ToC to which anchorname belongs. |
| |
| sub anchorNameBegin { |
| # Get arguments |
| my ($self, $aAnchorNameBegin, $aToc) = @_; |
| # Is another anchorName active? |
| if (defined($self->{_activeAnchorName})) { |
| # Yes, another anchorName is active; |
| # Show warning |
| print "Warn\n"; |
| $self->_showWarning( |
| HTML::TocGenerator::WARNING_NESTED_ANCHOR_PS_WITHIN_PS, |
| [$aAnchorNameBegin, $self->{_activeAnchorName}] |
| ); |
| } |
| # Store anchor name as output prefix |
| $self->{_outputPrefix} = $aAnchorNameBegin; |
| # Indicate active anchor name |
| $self->{_activeAnchorName} = $aAnchorNameBegin; |
| # Indicate anchor name end must be output |
| $self->{_doOutputAnchorNameEnd} = 1; |
| } # anchorNameBegin() |
| |
| |
| #--- HTML::TocInsertor::anchorNameEnd() --------------------------------------- |
| # function: Process anchor name end, generated by HTML::TocGenerator. |
| # args: - $aAnchorNameEnd: Anchor name end tag to output. |
| # - $aToc: Reference to ToC to which anchorname belongs. |
| |
| sub anchorNameEnd { |
| # Get arguments |
| my ($self, $aAnchorNameEnd) = @_; |
| # Store anchor name as output prefix |
| $self->{_outputSuffix} .= $aAnchorNameEnd; |
| # Indicate deactive anchor name |
| $self->{_activeAnchorName} = undef; |
| } # anchorNameEnd() |
| |
| |
| #--- HTML::TocInsertor::comment() --------------------------------------------- |
| # function: Process comment. |
| # args: - $aComment: comment text with '<!--' and '-->' tags stripped off. |
| |
| sub comment { |
| # Get arguments |
| my ($self, $aComment) = @_; |
| # Local variables |
| my ($tocInsertionPointToken, $doOutput, $origText); |
| # Allow ancestor to process the comment tag |
| $self->SUPER::comment($aComment); |
| # Assemble original comment |
| $origText = "<!--$aComment-->"; |
| # Must ToCs be inserted? |
| if ($self->{hti__Mode} & MODE_DO_INSERT) { |
| # Yes, ToCs must be inserted; |
| # Processing comment as ToC insertion point is successful? |
| if (! $self->_processTokenAsInsertionPoint( |
| HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment, undef, $origText |
| )) { |
| # No, comment isn't a ToC insertion point; |
| # Output comment normally |
| $self->_writeOrBufferOutput($origText); |
| } |
| } |
| } # comment() |
| |
| |
| #--- HTML::TocInsertor::declaration() ----------------------------------------- |
| # function: This function is called every time a declaration is encountered |
| # by HTML::Parser. |
| |
| sub declaration { |
| # Get arguments |
| my ($self, $aDeclaration) = @_; |
| # Allow ancestor to process the declaration tag |
| $self->SUPER::declaration($aDeclaration); |
| # Must ToCs be inserted? |
| if ($self->{hti__Mode} & MODE_DO_INSERT) { |
| # Yes, ToCs must be inserted; |
| # Processing declaration as ToC insertion point is successful? |
| if (! $self->_processTokenAsInsertionPoint( |
| HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration, undef, |
| "<!$aDeclaration>" |
| )) { |
| # No, declaration isn't a ToC insertion point; |
| # Output declaration normally |
| $self->_writeOrBufferOutput("<!$aDeclaration>"); |
| } |
| } |
| } # declaration() |
| |
| |
| #--- HTML::TocInsertor::end() ------------------------------------------------- |
| # function: This function is called every time a closing tag is encountered |
| # by HTML::Parser. |
| # args: - $aTag: tag name (in lower case). |
| |
| sub end { |
| # Get arguments |
| my ($self, $aTag, $aOrigText) = @_; |
| # Allow ancestor to process the end tag |
| $self->SUPER::end($aTag, $aOrigText); |
| # Must ToCs be inserted? |
| if ($self->{hti__Mode} & MODE_DO_INSERT) { |
| # Yes, ToCs must be inserted; |
| # Processing end tag as ToC insertion point is successful? |
| if (! $self->_processTokenAsInsertionPoint( |
| HTML::TocGenerator::TT_TOKENTYPE_END, $aTag, undef, $aOrigText |
| )) { |
| # No, end tag isn't a ToC insertion point; |
| # Output end tag normally |
| $self->_writeOrBufferOutput($aOrigText); |
| } |
| } |
| } # end() |
| |
| |
| #--- HTML::TocInsertor::insert() ---------------------------------------------- |
| # function: Insert ToC in string. |
| # args: - $aToc: (reference to array of) ToC object to insert |
| # - $aString: string to insert ToC in |
| # - $aOptions: hash reference with optional insertor options |
| |
| sub insert { |
| # Get arguments |
| my ($self, $aToc, $aString, $aOptions) = @_; |
| # Initialize TocInsertor batch |
| $self->_initializeInsertorBatch($aToc, $aOptions); |
| # Do insert Toc |
| $self->_insert($aString); |
| # Deinitialize TocInsertor batch |
| $self->_deinitializeInsertorBatch(); |
| } # insert() |
| |
| |
| #--- HTML::TocInsertor::insertIntoFile() -------------------------------------- |
| # function: Insert ToCs in file. |
| # args: - $aToc: (reference to array of) ToC object(s) to insert. |
| # - $aFile: (reference to array of) file(s) to parse for insertion |
| # points. |
| # - $aOptions: optional insertor options |
| |
| sub insertIntoFile { |
| # Get arguments |
| my ($self, $aToc, $aFile, $aOptions) = @_; |
| # Initialize TocInsertor batch |
| $self->_initializeInsertorBatch($aToc, $aOptions); |
| # Do insert ToCs into file |
| $self->_insertIntoFile($aFile); |
| # Deinitialize TocInsertor batch |
| $self->_deinitializeInsertorBatch(); |
| } # insertIntoFile() |
| |
| |
| #--- HTML::TocInsertor::number() ---------------------------------------------- |
| # function: Process heading number generated by HTML::Toc. |
| # args: - $aNumber |
| |
| sub number { |
| # Get arguments |
| my ($self, $aNumber) = @_; |
| # Store heading number as output suffix |
| $self->{_outputSuffix} .= $aNumber; |
| } # number() |
| |
| |
| #--- HTML::TocInsertor::propagateFile() --------------------------------------- |
| # function: Propagate ToC; generate & insert ToC, using file as input. |
| # args: - $aToc: (reference to array of) ToC object to insert |
| # - $aFile: (reference to array of) file to parse for insertion |
| # points. |
| # - $aOptions: optional insertor options |
| |
| sub propagateFile { |
| # Get arguments |
| my ($self, $aToc, $aFile, $aOptions) = @_; |
| # Local variables; |
| my ($file, @files); |
| # Initialize TocInsertor batch |
| $self->_initializeInsertorBatch($aToc, $aOptions); |
| # Dereference array reference or make array of file specification |
| @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile); |
| # Loop through files |
| foreach $file (@files) { |
| # Generate and insert ToC |
| $self->_generateFromFile($file); |
| } |
| # Deinitialize TocInsertor batch |
| $self->_deinitializeInsertorBatch(); |
| } # propagateFile() |
| |
| |
| #--- HTML::TocInsertor::start() ----------------------------------------------- |
| # function: This function is called every time an opening tag is encountered. |
| # args: - $aTag: tag name (in lower case). |
| # - $aAttr: reference to hash containing all tag attributes (in lower |
| # case). |
| # - $aAttrSeq: reference to array containing all tag attributes (in |
| # lower case) in the original order |
| # - $aOrigText: the original HTML text |
| |
| sub start { |
| # Get arguments |
| my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_; |
| # Local variables |
| my ($doOutput, $i, $tocToken, $tag, $anchorId); |
| # Let ancestor process the start tag |
| $self->SUPER::start($aTag, $aAttr, $aAttrSeq, $aOrigText); |
| # Must ToC be inserted? |
| if ($self->{hti__Mode} & MODE_DO_INSERT) { |
| # Yes, ToC must be inserted; |
| # Processing start tag as ToC insertion point is successful? |
| if (! $self->_processTokenAsInsertionPoint( |
| HTML::TocGenerator::TT_TOKENTYPE_START, $aTag, $aAttr, $aOrigText |
| )) { |
| # No, start tag isn't a ToC insertion point; |
| # Add anchor id? |
| if ($self->{_doAddAnchorIdToStartTag}) { |
| # Yes, anchor id must be added; |
| # Reset indicator; |
| $self->{_doAddAnchorIdToStartTag} = 0; |
| # Alias anchor id |
| $anchorId = $self->{_anchorId}; |
| # Attribute 'id' already exists? |
| if (defined($aAttr->{id})) { |
| # Yes, attribute 'id' already exists; |
| # Show warning |
| print STDERR "WARNING: Overwriting existing id attribute '" . |
| $aAttr->{id} . "' of tag $aOrigText\n"; |
| |
| # Add anchor id to start tag |
| $aOrigText =~ s/(id)=\S*([\s>])/$1=$anchorId$2/i; |
| } |
| else { |
| # No, attribute 'id' doesn't exist; |
| # Add anchor id to start tag |
| $aOrigText =~ s/>/ id=$anchorId>/; |
| } |
| } |
| # Output start tag normally |
| $self->_writeOrBufferOutput($aOrigText); |
| } |
| } |
| } # start() |
| |
| |
| #--- HTML::TocInsertor::text() ------------------------------------------------ |
| # function: This function is called every time plain text is encountered. |
| # args: - @_: array containing data. |
| |
| sub text { |
| # Get arguments |
| my ($self, $aText) = @_; |
| # Let ancestor process the text |
| $self->SUPER::text($aText); |
| # Must ToC be inserted? |
| if ($self->{hti__Mode} & MODE_DO_INSERT) { |
| # Yes, ToC must be inserted; |
| # Processing text as ToC insertion point is successful? |
| if (! $self->_processTokenAsInsertionPoint( |
| HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText, undef, $aText |
| )) { |
| # No, text isn't a ToC insertion point; |
| # Output text normally |
| $self->_writeOrBufferOutput($aText); |
| } |
| } |
| } # text() |
| |
| |
| |
| |
| #=== HTML::_TokenTipParser ==================================================== |
| # function: Parse 'TIP tokens'. 'TIP tokens' mark HTML code which is to be |
| # used as the ToC Insertion Point. |
| # note: Used internally. |
| |
| package HTML::_TokenTipParser; |
| |
| |
| BEGIN { |
| use vars qw(@ISA); |
| |
| @ISA = qw(HTML::_TokenTocParser); |
| } |
| |
| |
| END {} |
| |
| |
| #--- HTML::_TokenTipParser::new() --------------------------------------------- |
| # function: Constructor |
| |
| sub new { |
| # Get arguments |
| my ($aType, $aTokenArray) = @_; |
| # Create instance |
| my $self = $aType->SUPER::new; |
| # Reference token array |
| $self->{tokens} = $aTokenArray; |
| # Reference to last added token |
| $self->{_lastAddedToken} = undef; |
| $self->{_lastAddedTokenType} = undef; |
| # Return instance |
| return $self; |
| } # new() |
| |
| |
| #--- HTML::_TokenTipParser::_processAttributes() ------------------------------ |
| # function: Process attributes. |
| # args: - $aAttributes: Attributes to parse. |
| |
| sub _processAttributes { |
| # Get arguments |
| my ($self, $aAttributes) = @_; |
| # Local variables |
| my (%includeAttributes, %excludeAttributes); |
| |
| # Parse attributes |
| $self->_parseAttributes( |
| $aAttributes, \%includeAttributes, \%excludeAttributes |
| ); |
| # Include attributes are specified? |
| if (keys(%includeAttributes) > 0) { |
| # Yes, include attributes are specified; |
| # Store include attributes |
| @${$self->{_lastAddedToken}}[ |
| HTML::TocInsertor::TIP_INCLUDE_ATTRIBUTES |
| ] = \%includeAttributes; |
| } |
| # Exclude attributes are specified? |
| if (keys(%excludeAttributes) > 0) { |
| # Yes, exclude attributes are specified; |
| # Store exclude attributes |
| @${$self->{_lastAddedToken}}[ |
| HTML::TocInsertor::TIP_EXCLUDE_ATTRIBUTES |
| ] = \%excludeAttributes; |
| } |
| } # _processAttributes() |
| |
| |
| #--- HTML::_TokenTipParser::_processToken() ----------------------------------- |
| # function: Process token. |
| # args: - $aTokenType: Type of token to process. |
| # - $aTag: Tag of token. |
| |
| sub _processToken { |
| # Get arguments |
| my ($self, $aTokenType, $aTag) = @_; |
| # Local variables |
| my ($tokenArray, $index); |
| # Push element on array of update tokens |
| $index = push(@{$self->{tokens}[$aTokenType]}, []) - 1; |
| # Alias token array to add element to |
| $tokenArray = $self->{tokens}[$aTokenType]; |
| # Indicate last updated token array element |
| $self->{_lastAddedTokenType} = $aTokenType; |
| $self->{_lastAddedToken} = \$$tokenArray[$index]; |
| # Add fields |
| $$tokenArray[$index][HTML::TocInsertor::TIP_TOC] = $self->{_toc}; |
| $$tokenArray[$index][HTML::TocInsertor::TIP_TOKEN_ID] = $aTag; |
| $$tokenArray[$index][HTML::TocInsertor::TIP_PREPOSITION] = |
| $self->{_preposition}; |
| } # _processToken() |
| |
| |
| #--- HTML::_TokenTipParser::comment() ----------------------------------------- |
| # function: Process comment. |
| # args: - $aComment: comment text with '<!--' and '-->' tags stripped off. |
| |
| sub comment { |
| # Get arguments |
| my ($self, $aComment) = @_; |
| # Process token |
| $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment); |
| } # comment() |
| |
| |
| #--- HTML::_TokenTipParser::declaration() -------------------------------- |
| # function: This function is called every time a markup declaration is |
| # encountered by HTML::Parser. |
| # args: - $aDeclaration: Markup declaration. |
| |
| sub declaration { |
| # Get arguments |
| my ($self, $aDeclaration) = @_; |
| # Process token |
| $self->_processToken( |
| HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration |
| ); |
| } # declaration() |
| |
| |
| #--- HTML::_TokenTipParser::end() ---------------------------------------- |
| # function: This function is called every time a closing tag is encountered |
| # by HTML::Parser. |
| # args: - $aTag: tag name (in lower case). |
| |
| sub end { |
| # Get arguments |
| my ($self, $aTag, $aOrigText) = @_; |
| # Process token |
| $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag); |
| } # end() |
| |
| |
| #--- HTML::_TokenTipParser->setPreposition() ---------------------------------- |
| # function: Set current preposition. |
| |
| sub setPreposition { |
| # Get arguments |
| my ($self, $aPreposition) = @_; |
| # Set current ToC |
| $self->{_preposition} = $aPreposition; |
| } # setPreposition() |
| |
| |
| #--- HTML::_TokenTipParser->setToc() ------------------------------------------ |
| # function: Set current ToC. |
| |
| sub setToc { |
| # Get arguments |
| my ($self, $aToc) = @_; |
| # Set current ToC |
| $self->{_toc} = $aToc; |
| } # setToc() |
| |
| |
| #--- HTML::_TokenTipParser::start() -------------------------------------- |
| # function: This function is called every time an opening tag is encountered. |
| # args: - $aTag: tag name (in lower case). |
| # - $aAttr: reference to hash containing all tag attributes (in lower |
| # case). |
| # - $aAttrSeq: reference to array containing all attribute keys (in |
| # lower case) in the original order |
| # - $aOrigText: the original HTML text |
| |
| sub start { |
| # Get arguments |
| my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_; |
| # Process token |
| $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag); |
| # Process attributes |
| $self->_processAttributes($aAttr); |
| } # start() |
| |
| |
| #--- HTML::_TokenTipParser::text() --------------------------------------- |
| # function: This function is called every time plain text is encountered. |
| # args: - @_: array containing data. |
| |
| sub text { |
| # Get arguments |
| my ($self, $aText) = @_; |
| # Was token already created and is last added token of type 'text'? |
| if ( |
| defined($self->{_lastAddedToken}) && |
| $self->{_lastAddedTokenType} == HTML::TocGenerator::TT_TOKENTYPE_TEXT |
| ) { |
| # Yes, token is already created; |
| # Add tag to existing token |
| @${$self->{_lastAddedToken}}[HTML::TocGenerator::TT_TAG_BEGIN] .= $aText; |
| } |
| else { |
| # No, token isn't created; |
| # Process token |
| $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText); |
| } |
| } # text() |
| |
| |
| 1; |