1794 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			1794 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| #=== HTML::TocGenerator =======================================================
 | |
| # function: Generate 'HTML::Toc' table of contents.
 | |
| # note:     - 'TT' is an abbrevation of 'TocToken'.
 | |
| 
 | |
| 
 | |
| package HTML::TocGenerator;
 | |
| 
 | |
| 
 | |
| use strict;
 | |
| use HTML::Parser;
 | |
| 
 | |
| 
 | |
| BEGIN {
 | |
| 	use vars qw(@ISA $VERSION);
 | |
| 
 | |
| 	$VERSION = '0.91';
 | |
| 
 | |
| 	@ISA = qw(HTML::Parser);
 | |
| }
 | |
| 
 | |
| 
 | |
| 	# Warnings
 | |
| use constant WARNING_NESTED_ANCHOR_PS_WITHIN_PS               => 1;
 | |
| use constant WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS => 2;
 | |
| 
 | |
| 
 | |
| use constant TOC_TOKEN_ID       => 0;
 | |
| use constant TOC_TOKEN_INCLUDE  => 1;
 | |
| use constant TOC_TOKEN_EXCLUDE  => 2;
 | |
| use constant TOC_TOKEN_TOKENS   => 3;
 | |
| use constant TOC_TOKEN_GROUP    => 4;
 | |
| use constant TOC_TOKEN_TOC      => 5;
 | |
| 
 | |
| 	# Token types
 | |
| use constant TT_TAG_BEGIN                => 0;
 | |
| use constant TT_TAG_END                  => 1;
 | |
| use constant TT_TAG_TYPE_END             => 2;
 | |
| use constant TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
 | |
| use constant TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
 | |
| use constant TT_INCLUDE_ATTRIBUTES_END   => 5;
 | |
| use constant TT_EXCLUDE_ATTRIBUTES_END   => 6;
 | |
| use constant TT_GROUP                    => 7;
 | |
| use constant TT_TOC                      => 8;
 | |
| use constant TT_ATTRIBUTES_TOC           => 9;
 | |
| 
 | |
| 
 | |
| use constant CONTAINMENT_INCLUDE => 0;
 | |
| use constant CONTAINMENT_EXCLUDE => 1;
 | |
| 
 | |
| use constant TEMPLATE_ANCHOR            => '$groupId."-".$node';
 | |
| use constant TEMPLATE_ANCHOR_HREF       => 
 | |
| 					'"<a href=#".' . TEMPLATE_ANCHOR . '.">"';
 | |
| use constant TEMPLATE_ANCHOR_HREF_FILE  => 
 | |
| 					'"<a href=".$file."#".' . TEMPLATE_ANCHOR . '.">"';
 | |
| use constant TEMPLATE_ANCHOR_NAME       => 
 | |
| 					'"<a name=".' . TEMPLATE_ANCHOR . '.">"';
 | |
| 
 | |
| use constant TEMPLATE_TOKEN_NUMBER      => '"$node  "';
 | |
| 
 | |
| 
 | |
| use constant TT_TOKENTYPE_START        => 0;
 | |
| use constant TT_TOKENTYPE_END          => 1;
 | |
| use constant TT_TOKENTYPE_TEXT         => 2;
 | |
| use constant TT_TOKENTYPE_COMMENT      => 3;
 | |
| use constant TT_TOKENTYPE_DECLARATION  => 4;
 | |
| 
 | |
| 
 | |
| END {}
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::new() ------------------------------------------------
 | |
| # function: Constructor
 | |
| 
 | |
| sub new {
 | |
| 		# Get arguments
 | |
| 	my ($aType) = @_;
 | |
| 	my $self = $aType->SUPER::new;
 | |
| 		# Bias to not generate ToC
 | |
| 	$self->{_doGenerateToc} = 0;
 | |
| 		# Bias to not use global groups
 | |
| 	$self->{_doUseGroupsGlobal} = 0;
 | |
| 		# Output
 | |
| 	$self->{output} = "";
 | |
| 		# Reset internal variables
 | |
| 	$self->_resetBatchVariables();
 | |
| 
 | |
| 	$self->{options} = {};
 | |
| 
 | |
| 	return $self;
 | |
| }  # new()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_deinitializeBatch() ---------------------------------
 | |
| 
 | |
| sub _deinitializeBatch() {
 | |
| 		# Get arguments
 | |
| 	my ($self) = @_;
 | |
| }  # _deinitializeBatch()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_deinitializeExtenderBatch() -------------------------
 | |
| 
 | |
| sub _deinitializeExtenderBatch() {
 | |
| 		# Get arguments
 | |
| 	my ($self) = @_;
 | |
| 		# Do general batch deinitialization
 | |
| 	$self->_deinitializeBatch();
 | |
| 		# Indicate end of ToC generation
 | |
| 	$self->{_doGenerateToc} = 0;
 | |
| 		# Reset batch variables
 | |
| 	$self->_resetBatchVariables();
 | |
| }  # _deinitializeExtenderBatch()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_deinitializeGeneratorBatch() ------------------------
 | |
| 
 | |
| sub _deinitializeGeneratorBatch() {
 | |
| 		# Get arguments
 | |
| 	my ($self) = @_;
 | |
| 		# Do 'extender' batch deinitialization
 | |
| 	$self->_deinitializeExtenderBatch();
 | |
| }  # _deinitializeBatchGenerator()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_doesHashContainHash() -------------------------------
 | |
| # function: Determines whether hash1 matches regular expressions of hash2.
 | |
| # args:     - $aHash1
 | |
| #           - $aHash2
 | |
| #           - $aContainmentType: 0 (include) or 1 (exclude)
 | |
| # returns:  True (1) if hash1 satisfies hash2, 0 if not.  For example, with the
 | |
| #           following hashes:
 | |
| #
 | |
| #              %hash1 = {							%hash2 = {
 | |
| #                 'class' => 'header'				'class' => '^h'
 | |
| #                 'id'    => 'intro'         }
 | |
| #              }
 | |
| #
 | |
| #           the routine will return 1 if 'aContainmentType' equals 0, cause
 | |
| #           'hash1' satisfies the conditions of 'hash2'.  The routine will
 | |
| #           return 0 if 'aContainmentType' equals 1, cause 'hash1' doesn't
 | |
| #           exclude the conditions of 'hash2'.
 | |
| # note:     Class function.
 | |
| 
 | |
| sub _doesHashContainHash {
 | |
| 		# Get arguments
 | |
| 	my ($aHash1, $aHash2, $aContainmentType) = @_;
 | |
| 		# Local variables
 | |
| 	my ($key1, $value1, $key2, $value2, $result);
 | |
| 		# Bias to success
 | |
| 	$result = 1;
 | |
| 		# Loop through hash2
 | |
| 	HASH2: while (($key2, $value2) = each %$aHash2) {
 | |
| 		# Yes, values are available;
 | |
| 			# Get value1
 | |
| 		$value1 = $aHash1->{$key2};
 | |
| 			# Does value1 match criteria of value2?
 | |
| 		if (defined($value1) && $value1 =~ m/$value2/) {
 | |
| 			# Yes, value1 matches criteria of value2;
 | |
| 				# Containment type was exclude?
 | |
| 			if ($aContainmentType == CONTAINMENT_EXCLUDE) {
 | |
| 				# Yes, containment type was exclude;
 | |
| 					# Indicate condition fails
 | |
| 				$result = 0;
 | |
| 					# Reset 'each' iterator which we're going to break
 | |
| 				keys %$aHash2;
 | |
| 					# Break loop
 | |
| 				last HASH2;
 | |
| 			}
 | |
| 		}
 | |
| 		else {
 | |
| 			# No, value1 didn't match criteria of value2;
 | |
| 				# Containment type was include?
 | |
| 			if ($aContainmentType == CONTAINMENT_INCLUDE) {
 | |
| 				# Yes, containment type was include;
 | |
| 					# Indicate condition fails
 | |
| 				$result = 0;
 | |
| 					# Reset 'each' iterator which we're going to break
 | |
| 				keys %$aHash2;
 | |
| 					# Break loop
 | |
| 				last HASH2;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 		# Return value
 | |
| 	return $result;
 | |
| }  # _doesHashContainHash()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_extend() --------------------------------------------
 | |
| # function: Extend ToC.
 | |
| #           - $aString: String to parse.
 | |
| 
 | |
| sub _extend {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aFile) = @_;
 | |
| 		# Local variables
 | |
| 	my ($file);
 | |
| 		# Parse string
 | |
| 	$self->parse($aFile);
 | |
| 		# Flush remaining buffered text
 | |
| 	$self->eof();
 | |
| }  # _extend()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_extendFromFile() ------------------------------------
 | |
| # function: Extend ToC.
 | |
| #           - $aFile: (reference to array of) file to parse.
 | |
| 
 | |
| sub _extendFromFile {
 | |
| 		# 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) {
 | |
| 			# Store filename
 | |
| 		$self->{_currentFile} = $file;
 | |
| 			# Parse file
 | |
| 		$self->parse_file($file);
 | |
| 			# Flush remaining buffered text
 | |
| 		$self->eof();
 | |
| 	}
 | |
| }  # _extendFromFile()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_formatHeadingLevel() --------------------------------
 | |
| # function: Format heading level.
 | |
| # args:     - $aLevel: Level of current heading
 | |
| #           - $aClass: Class of current heading
 | |
| #           - $aGroup: Group of current heading
 | |
| #           - $aToc: Toc of current heading
 | |
| 
 | |
| sub _formatHeadingLevel {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
 | |
| 		# Local variables
 | |
| 	my ($result, $headingNumber, $numberingStyle);
 | |
| 
 | |
| 	$headingNumber = $self->_getGroupIdManager($aToc)->
 | |
| 		{levels}{$aClass}[$aLevel - 1] || 0;
 | |
| 
 | |
| 		# Alias numbering style of current group
 | |
| 	$numberingStyle = $aGroup->{numberingStyle};
 | |
| 
 | |
| 	SWITCH: {
 | |
| 		if ($numberingStyle eq "decimal") {
 | |
| 			$result = $headingNumber;
 | |
| 			last SWITCH;
 | |
| 		}
 | |
| 		if ($numberingStyle eq "lower-alpha") {
 | |
| 			$result = chr($headingNumber + ord('a') - 1);
 | |
| 			last SWITCH;
 | |
| 		}
 | |
| 		if ($numberingStyle eq "upper-alpha") {
 | |
| 			$result = chr($headingNumber + ord('A') - 1);
 | |
| 			last SWITCH;
 | |
| 		}
 | |
| 		if ($numberingStyle eq "lower-roman") {
 | |
| 			require Roman;
 | |
| 			$result = Roman::roman($headingNumber);
 | |
| 			last SWITCH;
 | |
| 		}
 | |
| 		if ($numberingStyle eq "upper-roman") {
 | |
| 			require Roman;
 | |
| 			$result = Roman::Roman($headingNumber);
 | |
| 			last SWITCH;
 | |
| 		}
 | |
| 		die "Unknown case: $numberingStyle";
 | |
| 	}
 | |
| 		# Return value
 | |
| 	return $result;
 | |
| }	# _formatHeadingLevel()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_formatTocNode() -------------------------------------
 | |
| # function: Format heading node.
 | |
| # args:     - $aLevel: Level of current heading
 | |
| #           - $aClass: Class of current heading
 | |
| #           - $aGroup: Group of current heading
 | |
| #           - $aToc: Toc of current heading
 | |
| 
 | |
| sub _formatTocNode {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
 | |
| 		# Local variables
 | |
| 	my ($result, $level, $levelGroups);
 | |
| 
 | |
| 		# Alias 'levelGroups' of right 'groupId'
 | |
| 	$levelGroups = $aToc->{_levelGroups}{$aGroup->{'groupId'}};
 | |
| 		# Loop through levels
 | |
| 	for ($level = 1; $level <= $aLevel; $level++) {
 | |
| 			# If not first level, add dot
 | |
| 		$result = ($result ? $result . "." : $result);
 | |
| 			# Format heading level using argument group
 | |
| 		$result .= $self->_formatHeadingLevel(
 | |
| 			$level, $aClass, @{$levelGroups}[$level - 1], $aToc
 | |
| 		);
 | |
| 	}
 | |
| 		# Return value
 | |
| 	return $result;
 | |
| }  # _formatTocNode()
 | |
|      	
 | |
|      	
 | |
| #--- HTML::TocGenerator::_generate() ------------------------------------------
 | |
| # function: Generate ToC.
 | |
| # args:     - $aString: Reference to string to parse
 | |
| 
 | |
| sub _generate {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aString) = @_;
 | |
| 		# Local variables
 | |
| 	my ($toc);
 | |
| 		# Loop through ToCs
 | |
| 	foreach $toc (@{$self->{_tocs}}) {
 | |
| 			# Clear ToC
 | |
| 		$toc->clear();
 | |
| 	}
 | |
| 		# Extend ToCs
 | |
| 	$self->_extend($aString);
 | |
| }  # _generate()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_generateFromFile() ----------------------------------
 | |
| # function: Generate ToC.
 | |
| # args:     - $aFile: (reference to array of) file to parse.
 | |
| 
 | |
| sub _generateFromFile {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aFile) = @_;
 | |
| 		# Local variables
 | |
| 	my ($toc);
 | |
| 		# Loop through ToCs
 | |
| 	foreach $toc (@{$self->{_tocs}}) {
 | |
| 			# Clear ToC
 | |
| 		$toc->clear();
 | |
| 	}
 | |
| 		# Extend ToCs
 | |
| 	$self->_extendFromFile($aFile);
 | |
| }  # _generateFromFile()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_getGroupIdManager() ---------------------------------
 | |
| # function: Get group id manager.
 | |
| # args:     - $aToc: Active ToC.
 | |
| # returns:  Group id levels.
 | |
| 
 | |
| sub _getGroupIdManager {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aToc) = @_;
 | |
| 		# Local variables
 | |
| 	my ($result);
 | |
| 		# Global groups?
 | |
| 	if ($self->{options}{'doUseGroupsGlobal'}) {
 | |
| 		# Yes, global groups;
 | |
| 		$result = $self;
 | |
| 	}
 | |
| 	else {
 | |
| 		# No, local groups;
 | |
| 		$result = $aToc;
 | |
| 	}
 | |
| 		# Return value
 | |
| 	return $result;
 | |
| }  # _getGroupIdManager()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_initializeBatch() -----------------------------------
 | |
| # function: Initialize batch.  This function is called once when a parse batch
 | |
| #           is started.
 | |
| # args:     - $aTocs: Reference to array of tocs.
 | |
| 
 | |
| sub _initializeBatch {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTocs) = @_;
 | |
| 		# Local variables
 | |
| 	my ($toc);
 | |
| 
 | |
| 		# Store reference to tocs
 | |
| 		
 | |
| 		# Is ToC specification reference to array?
 | |
| 	if (ref($aTocs) =~ m/ARRAY/) {
 | |
| 		# Yes, ToC specification is reference to array;
 | |
| 			# Store array reference
 | |
| 		$self->{_tocs} = $aTocs;
 | |
| 	}
 | |
| 	else {
 | |
| 		# No, ToC specification is reference to ToC object;
 | |
| 			# Wrap reference in array reference, containing only one element
 | |
| 		$self->{_tocs} = [$aTocs];
 | |
| 	}
 | |
| 		# Loop through ToCs
 | |
| 	foreach $toc (@{$self->{_tocs}}) {
 | |
| 			# Parse ToC options
 | |
| 		$toc->parseOptions();
 | |
| 	}
 | |
| }  # _initializeBatch()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_initializeExtenderBatch() --------------------------
 | |
| # function: Initialize 'extender' batch.  This function is called once when a 
 | |
| #           parse batch is started.
 | |
| # args:     - $aTocs: Reference to array of tocs.
 | |
| 
 | |
| sub _initializeExtenderBatch {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTocs) = @_;
 | |
| 		# Do general batch initialization
 | |
| 	$self->_initializeBatch($aTocs);
 | |
| 		# Parse ToC options
 | |
| 	$self->_parseTocOptions();
 | |
| 		# Indicate start of batch
 | |
| 	$self->{_doGenerateToc} = 1;
 | |
| }  # _initializeExtenderBatch()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_initializeGeneratorBatch() --------------------------
 | |
| # function: Initialize generator batch.  This function is called once when a 
 | |
| #           parse batch is started.
 | |
| # args:     - $aTocs: Reference to array of tocs.
 | |
| #           - $aOptions: optional options
 | |
| 
 | |
| sub _initializeGeneratorBatch {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTocs, $aOptions) = @_;
 | |
| 		# Add invocation options
 | |
| 	$self->setOptions($aOptions);
 | |
| 		# Option 'doUseGroupsGlobal' specified?
 | |
| 	if (!defined($self->{options}{'doUseGroupsGlobal'})) {
 | |
| 		# No, options 'doUseGroupsGlobal' not specified;
 | |
| 			# Default to no 'doUseGroupsGlobal'
 | |
| 		$self->{options}{'doUseGroupsGlobal'} = 0;
 | |
| 	}
 | |
| 		# Global groups?
 | |
| 	if ($self->{options}{'doUseGroupsGlobal'}) {
 | |
| 		# Yes, global groups;
 | |
| 			# Reset groups and levels
 | |
| 		$self->_resetStackVariables();
 | |
| 	}
 | |
| 		# Do 'extender' batch initialization
 | |
| 	$self->_initializeExtenderBatch($aTocs);
 | |
| }  # _initializeGeneratorBatch()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_linkTocToToken() ------------------------------------
 | |
| # function: Link ToC to token.
 | |
| # args:     - $aToc: ToC to add token to.
 | |
| #           - $aFile
 | |
| #           - $aGroupId
 | |
| #           - $aLevel
 | |
| #           - $aNode
 | |
| #           - $aGroupLevel
 | |
| #           - $aLinkType
 | |
| #           - $aTokenAttributes: reference to hash containing attributes of 
 | |
| #                currently parsed token
 | |
| 
 | |
| sub _linkTocToToken {
 | |
| 		# Get arguments
 | |
| 	my (
 | |
| 		$self, $aToc, $aFile, $aGroupId, $aLevel, $aNode, $aGroupLevel, 
 | |
| 		$aDoLinkToId, $aTokenAttributes
 | |
| 	) = @_;
 | |
| 		# Local variables
 | |
| 	my ($file, $groupId, $level, $node, $anchorName);
 | |
| 	my ($doInsertAnchor, $doInsertId);
 | |
| 
 | |
| 		# Fill local arguments to be used by templates
 | |
| 	$file    = $aFile;
 | |
| 	$groupId = $aGroupId;
 | |
| 	$level   = $aLevel;
 | |
| 	$node    = $aNode;
 | |
| 	
 | |
| 		# Assemble anchor name
 | |
| 	$anchorName = 
 | |
| 		ref($aToc->{_templateAnchorName}) eq "CODE" ?
 | |
| 			&{$aToc->{_templateAnchorName}}(
 | |
| 				$aFile, $aGroupId, $aLevel, $aNode
 | |
| 			) : 
 | |
| 			eval($aToc->{_templateAnchorName});
 | |
| 
 | |
| 		# Bias to insert anchor name
 | |
| 	$doInsertAnchor = 1;
 | |
| 	$doInsertId     = 0;
 | |
| 		# Link to 'id'?
 | |
| 	if ($aDoLinkToId) {
 | |
| 		# Yes, link to 'id';
 | |
| 			# Indicate to insert anchor id
 | |
| 		$doInsertAnchor = 0;
 | |
| 		$doInsertId     = 1;
 | |
| 			# Id attribute is available?
 | |
| 		if (defined($aTokenAttributes->{id})) {
 | |
| 			# Yes, id attribute is available;
 | |
| 				# Use existing ids?
 | |
| 			if ($aToc->{options}{'doUseExistingIds'}) {
 | |
| 				# Yes, use existing ids;
 | |
| 					# Use existing id
 | |
| 				$anchorName = $aTokenAttributes->{id};
 | |
| 					# Indicate to not insert id
 | |
| 				$doInsertId = 0;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 	else {
 | |
| 		# No, link to 'name';
 | |
| 			# Anchor name is currently active?
 | |
| 		if (defined($self->{_activeAnchorName})) {
 | |
| 			# Yes, anchor name is currently active;
 | |
| 				# Use existing anchors?
 | |
| 			if ($aToc->{options}{'doUseExistingAnchors'}) {
 | |
| 				# Yes, use existing anchors;
 | |
| 					# Use existing anchor name
 | |
| 				$anchorName = $self->{_activeAnchorName};
 | |
| 					# Indicate to not insert anchor name
 | |
| 				$doInsertAnchor = 0;
 | |
| 			}
 | |
| 			else {
 | |
| 				# No, don't use existing anchors; insert new anchor;
 | |
| 					# 
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 		# Add reference to ToC
 | |
| 	$aToc->{_toc} .= 
 | |
| 		ref($aToc->{_templateAnchorHrefBegin}) eq "CODE" ?
 | |
| 			&{$aToc->{_templateAnchorHrefBegin}}(
 | |
| 				$aFile, $aGroupId, $aLevel, $aNode, $anchorName
 | |
| 			) : 
 | |
| 			eval($aToc->{_templateAnchorHrefBegin});
 | |
| 
 | |
| 		# Bias to not output anchor name end
 | |
| 	$self->{_doOutputAnchorNameEnd} = 0;
 | |
| 		# Must anchor be inserted?
 | |
| 	if ($doInsertAnchor) {
 | |
| 		# Yes, anchor must be inserted;
 | |
| 			# Allow adding of anchor name begin token to text by calling 
 | |
| 			# 'anchorNameBegin' method
 | |
| 		$self->anchorNameBegin(
 | |
| 			ref($aToc->{_templateAnchorNameBegin}) eq "CODE" ?
 | |
| 				&{$aToc->{_templateAnchorNameBegin}}(
 | |
| 					$aFile, $aGroupId, $aLevel, $aNode, $anchorName
 | |
| 				) :
 | |
| 				eval($aToc->{_templateAnchorNameBegin}),
 | |
| 			$aToc
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 		# Must anchorId attribute be inserted?
 | |
| 	if ($doInsertId) {
 | |
| 		# Yes, anchorId attribute must be inserted;
 | |
| 			# Allow adding of anchorId attribute to text by calling 'anchorId'
 | |
| 			# method
 | |
| 		$self->anchorId($anchorName);
 | |
| 	}
 | |
| }  # _linkTocToToken()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_outputAnchorNameEndConditionally() ------------------
 | |
| # function: Output 'anchor name end' if necessary
 | |
| # args:     - $aToc: ToC of which 'anchor name end' must be output.
 | |
| 
 | |
| sub _outputAnchorNameEndConditionally {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aToc) = @_;
 | |
| 		# Must anchor name end be output?
 | |
| 	if ($self->{_doOutputAnchorNameEnd}) {
 | |
| 		# Yes, output anchor name end;
 | |
| 			# Allow adding of anchor to text by calling 'anchorNameEnd' 
 | |
| 			# method
 | |
| 		$self->anchorNameEnd(
 | |
| 			ref($aToc->{_templateAnchorNameEnd}) eq "CODE" ?
 | |
| 				&{$aToc->{_templateAnchorNameEnd}} :
 | |
| 				eval($aToc->{_templateAnchorNameEnd}),
 | |
| 			$aToc
 | |
| 		);
 | |
| 	}
 | |
| }  # _outputAnchorNameEndConditionally()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_parseTocOptions() -----------------------------------
 | |
| # function: Parse ToC options.
 | |
| 
 | |
| sub _parseTocOptions {
 | |
| 		# Get arguments
 | |
| 	my ($self) = @_;
 | |
| 		# Local variables
 | |
| 	my ($toc, $group, $tokens, $tokenType, $i);
 | |
| 		# Create parsers for ToC tokens
 | |
| 	$self->{_tokensTocBegin} = [];
 | |
| 	my $tokenTocBeginParser = HTML::_TokenTocBeginParser->new(
 | |
| 		$self->{_tokensTocBegin}
 | |
| 	);
 | |
| 	my $tokenTocEndParser = HTML::_TokenTocEndParser->new();
 | |
| 		# Loop through ToCs
 | |
| 	foreach $toc (@{$self->{_tocs}}) {
 | |
| 			# Reference parser ToC to current ToC
 | |
| 		$tokenTocBeginParser->setToc($toc);
 | |
| 			# Loop through 'tokenToToc' groups
 | |
| 		foreach $group (@{$toc->{options}{'tokenToToc'}}) {
 | |
| 				# Reference parser group to current group
 | |
| 			$tokenTocBeginParser->setGroup($group);
 | |
| 				# Parse 'tokenToToc' group
 | |
| 			$tokenTocBeginParser->parse($group->{'tokenBegin'});
 | |
| 				# Flush remaining buffered text
 | |
| 			$tokenTocBeginParser->eof();
 | |
| 			$tokenTocEndParser->parse(
 | |
| 				$group->{'tokenEnd'}, 
 | |
| 				$tokenTocBeginParser->{_lastAddedToken},
 | |
| 				$tokenTocBeginParser->{_lastAddedTokenType}
 | |
| 			);
 | |
| 				# Flush remaining buffered text
 | |
| 			$tokenTocEndParser->eof();
 | |
| 		}
 | |
| 	}
 | |
| }  # _parseTocOptions()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_processTocEndingToken() -----------------------------
 | |
| # function: Process ToC-ending-token.
 | |
| # args:     - $aTocToken: token which acts as ToC-ending-token.
 | |
| 
 | |
| sub _processTocEndingToken {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTocToken) = @_;
 | |
| 		# Local variables
 | |
| 	my ($toc);
 | |
| 		# Aliases
 | |
| 	$toc = $aTocToken->[TT_TOC];
 | |
| 		# Link ToC to tokens?
 | |
| 	if ($toc->{options}{'doLinkToToken'}) {
 | |
| 		# Yes, link ToC to tokens;
 | |
| 			# Add anchor href end
 | |
| 		$toc->{_toc} .= 
 | |
| 			(ref($toc->{_templateAnchorHrefEnd}) eq "CODE") ?
 | |
| 				&{$toc->{_templateAnchorHrefEnd}} : 
 | |
| 				eval($toc->{_templateAnchorHrefEnd});
 | |
| 
 | |
| 			# Output anchor name end only if necessary
 | |
| 		$self->_outputAnchorNameEndConditionally($toc);
 | |
| 	}
 | |
| }  # _processTocEndingToken()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_processTocStartingToken() ---------------------------
 | |
| # function: Process ToC-starting-token.
 | |
| # args:     - $aTocToken: token which acts as ToC-starting-token.
 | |
| #           - $aTokenType: type of token.  Can be either TT_TOKENTYPE_START,
 | |
| #                _END, _TEXT, _COMMENT or _DECLARATION.
 | |
| #           - $aTokenAttributes: reference to hash containing attributes of 
 | |
| #                currently parsed token
 | |
| #           - $aTokenOrigText: reference to original token text
 | |
| 
 | |
| sub _processTocStartingToken {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTocToken, $aTokenType, $aTokenAttributes, $aTokenOrigText) = @_;
 | |
| 		# Local variables
 | |
| 	my ($i, $level, $doLinkToId, $node, $groupLevel);
 | |
| 	my ($file, $tocTokenId, $groupId, $toc, $attribute);
 | |
| 		# Aliases
 | |
| 	$file        = $self->{_currentFile};
 | |
| 	$toc		    = $aTocToken->[TT_TOC];
 | |
| 	$level	    = $aTocToken->[TT_GROUP]{'level'};
 | |
| 	$groupId	    = $aTocToken->[TT_GROUP]{'groupId'};
 | |
| 
 | |
| 		# Retrieve 'doLinkToId' setting from either group options or toc options
 | |
| 	$doLinkToId = (defined($aTocToken->[TT_GROUP]{'doLinkToId'})) ?
 | |
| 		$aTocToken->[TT_GROUP]{'doLinkToId'} : $toc->{options}{'doLinkToId'}; 
 | |
| 	
 | |
| 		# Link to 'id' and tokenType isn't 'start'?
 | |
| 	if (($doLinkToId) && ($aTokenType != TT_TOKENTYPE_START)) {
 | |
| 		# Yes, link to 'id' and tokenType isn't 'start';
 | |
| 			# Indicate to *not* link to 'id'
 | |
| 		$doLinkToId = 0;
 | |
| 	}
 | |
| 
 | |
| 	if (ref($level) eq "CODE") {
 | |
| 		$level = &$level($self->{_currentFile}, $node);
 | |
| 	}
 | |
| 	if (ref($groupId) eq "CODE") {
 | |
| 		$groupId = &$groupId($self->{_currentFile}, $node);
 | |
| 	}
 | |
| 
 | |
| 		# Determine class level
 | |
| 
 | |
| 	my $groupIdManager = $self->_getGroupIdManager($toc);
 | |
| 		# Known group?
 | |
| 	if (!exists($groupIdManager->{groupIdLevels}{$groupId})) {
 | |
| 		# No, unknown group;
 | |
| 			# Add group
 | |
| 		$groupIdManager->{groupIdLevels}{$groupId} = keys(
 | |
| 			%{$groupIdManager->{groupIdLevels}}
 | |
| 		) + 1;
 | |
| 	}
 | |
| 	$groupLevel = $groupIdManager->{groupIdLevels}{$groupId};
 | |
| 
 | |
| 		# Temporarily allow symbolic references
 | |
| 	#no strict qw(refs);
 | |
| 		# Increase level
 | |
| 	$groupIdManager->{levels}{$groupId}[$level - 1] += 1;
 | |
| 		# Reset remaining levels of same group
 | |
| 	for ($i = $level; $i < @{$groupIdManager->{levels}{$groupId}}; $i++) {
 | |
| 		$groupIdManager->{levels}{$groupId}[$i] = 0;
 | |
| 	}
 | |
| 
 | |
| 		# Assemble numeric string indicating current level
 | |
| 	$node = $self->_formatTocNode(
 | |
| 		$level, $groupId, $aTocToken->[TT_GROUP], $toc
 | |
| 	);
 | |
| 
 | |
| 		# Add newline if _toc not empty
 | |
| 	if ($toc->{_toc}) { 
 | |
| 		$toc->{_toc} .= "\n";
 | |
| 	}
 | |
| 
 | |
| 		# Add toc item info
 | |
| 	$toc->{_toc} .= "$level $groupLevel $groupId $node " .
 | |
| 		$groupIdManager->{levels}{$groupId}[$level - 1] . " ";
 | |
| 
 | |
| 		# Add value of 'id' attribute if available
 | |
| 	if (defined($aTokenAttributes->{id})) {
 | |
| 		$toc->{_toc} .= $aTokenAttributes->{id};
 | |
| 	}
 | |
| 	$toc->{_toc} .= " ";
 | |
| 		# Link ToC to tokens?
 | |
| 	if ($toc->{options}{'doLinkToToken'}) {
 | |
| 		# Yes, link ToC to tokens;
 | |
| 			# Link ToC to token
 | |
| 		$self->_linkTocToToken(
 | |
| 			$toc, $file, $groupId, $level, $node, $groupLevel, $doLinkToId,
 | |
| 			$aTokenAttributes
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 		# Number tokens?
 | |
| 	if (
 | |
| 		$aTocToken->[TT_GROUP]{'doNumberToken'} || 
 | |
| 		(
 | |
| 			! defined($aTocToken->[TT_GROUP]{'doNumberToken'}) && 
 | |
| 			$toc->{options}{'doNumberToken'}
 | |
| 		)
 | |
| 	) {
 | |
| 		# Yes, number tokens;
 | |
| 			# Add number by calling 'number' method
 | |
| 		$self->number(
 | |
| 			ref($toc->{_templateTokenNumber}) eq "CODE" ?
 | |
| 				&{$toc->{_templateTokenNumber}}(
 | |
| 					$node, $groupId, $file, $groupLevel, $level, $toc
 | |
| 				) : 
 | |
| 				eval($toc->{_templateTokenNumber}),
 | |
| 			$toc
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 		# Must attribute be used as ToC text?
 | |
| 	if (defined($aTocToken->[TT_ATTRIBUTES_TOC])) {
 | |
| 		# Yes, attribute must be used as ToC text;
 | |
| 			# Loop through attributes
 | |
| 		foreach $attribute (@{$aTocToken->[TT_ATTRIBUTES_TOC]}) {
 | |
| 				# Attribute is available?
 | |
| 			if (defined($$aTokenAttributes{$attribute})) {
 | |
| 				# Yes, attribute is available;
 | |
| 					# Add attribute value to ToC
 | |
| 				$self->_processTocText($$aTokenAttributes{$attribute}, $toc);
 | |
| 			}
 | |
| 			else {
 | |
| 				# No, attribute isn't available;
 | |
| 					# Show warning
 | |
| 				$self->_showWarning(
 | |
| 					WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS,
 | |
| 					[$attribute, $$aTokenOrigText]
 | |
| 				);
 | |
| 			}
 | |
| 				# Output anchor name end only if necessary
 | |
| 			#$self->_outputAnchorNameEndConditionally($toc);
 | |
| 				# End attribute
 | |
| 			$self->_processTocEndingToken($aTocToken);
 | |
| 		}
 | |
| 	}
 | |
| 	else {
 | |
| 		# No, attribute mustn't be used as ToC text;
 | |
| 			# Add end token to 'end token array'
 | |
| 		push(
 | |
| 			@{$self->{_tokensTocEnd}[$aTocToken->[TT_TAG_TYPE_END]]}, $aTocToken
 | |
| 		);
 | |
| 	}
 | |
| }  # _processTocStartingToken()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_processTocText() ------------------------------------
 | |
| # function: This function processes text which must be added to the preliminary
 | |
| #           ToC.
 | |
| # args:     - $aText: Text to add to ToC.
 | |
| #           - $aToc: ToC to add text to.
 | |
| 
 | |
| sub _processTocText {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aText, $aToc) = @_;
 | |
| 		# Add text to ToC
 | |
| 	$aToc->{_toc} .= $aText;
 | |
| }  # _processTocText()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_processTokenAsTocEndingToken() ----------------------
 | |
| # function: Check for token being a token to use for triggering the end of
 | |
| #           a ToC line and process it accordingly.
 | |
| # args:     - $aTokenType: type of token: 'start', 'end', 'comment' or 'text'.
 | |
| #           - $aTokenId: token id of currently parsed token
 | |
| 
 | |
| sub _processTokenAsTocEndingToken {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTokenType, $aTokenId) = @_;
 | |
| 		# Local variables
 | |
| 	my ($i, $tokenId, $toc, $tokens);
 | |
| 		# Loop through dirty start tokens
 | |
| 	$i = 0;
 | |
| 
 | |
| 		# Alias token array of right type
 | |
| 	$tokens = $self->{_tokensTocEnd}[$aTokenType];
 | |
| 		# Loop through token array
 | |
| 	while ($i < scalar @$tokens) {
 | |
| 			# Aliases
 | |
| 		$tokenId = $tokens->[$i][TT_TAG_END];
 | |
| 			# Does current end tag equals dirty tag?
 | |
| 		if ($aTokenId eq $tokenId) {
 | |
| 			# Yes, current end tag equals dirty tag;
 | |
| 				# Process ToC-ending-token
 | |
| 			$self->_processTocEndingToken($tokens->[$i]);
 | |
| 				# Remove dirty tag from array, automatically advancing to
 | |
| 				# next token
 | |
| 			splice(@$tokens, $i, 1);
 | |
| 		}
 | |
| 		else {
 | |
| 			# No, current end tag doesn't equal dirty tag;
 | |
| 				# Advance to next token
 | |
| 			$i++;
 | |
| 		}
 | |
| 	}
 | |
| }  # _processTokenAsTocEndingToken()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_processTokenAsTocStartingToken() --------------------
 | |
| # function: Check for token being a ToC-starting-token and process it 
 | |
| #           accordingly.
 | |
| # args:     - $aTokenType: type of token.  Can be either TT_TOKENTYPE_START,
 | |
| #                _END, _TEXT, _COMMENT or _DECLARATION.
 | |
| #           - $aTokenId: token id of currently parsed token
 | |
| #           - $aTokenAttributes: reference to hash containing attributes of 
 | |
| #                currently parsed token
 | |
| #           - $aTokenOrigText: reference to original text of token
 | |
| # returns:  1 if successful, i.e. token is processed as ToC-starting-token, 0
 | |
| #           if not.
 | |
| 
 | |
| sub _processTokenAsTocStartingToken {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aTokenOrigText) = @_;
 | |
| 		# Local variables
 | |
| 	my ($level, $levelToToc, $groupId, $groupToToc);
 | |
| 	my ($result, $tocToken, $tagBegin, @tokensTocBegin, $fileSpec);
 | |
| 		# Bias to token not functioning as ToC-starting-token
 | |
| 	$result = 0;
 | |
| 		# Loop through start tokens of right type
 | |
| 	foreach $tocToken (@{$self->{_tokensTocBegin}[$aTokenType]}) {
 | |
| 			# Alias file filter
 | |
| 		$fileSpec = $tocToken->[TT_GROUP]{'fileSpec'};
 | |
| 			# File matches?
 | |
| 		if (!defined($fileSpec) || (
 | |
| 			defined($fileSpec) &&
 | |
| 			($self->{_currentFile} =~ m/$fileSpec/)
 | |
| 		)) {
 | |
| 			# Yes, file matches;
 | |
| 				# Alias tag begin
 | |
| 			$tagBegin = $tocToken->[TT_TAG_BEGIN];
 | |
| 				# Tag and attributes match?
 | |
| 			if (
 | |
| 				defined($tagBegin) && 
 | |
| 				($aTokenId =~ m/$tagBegin/) && 
 | |
| 				HTML::TocGenerator::_doesHashContainHash(
 | |
| 					$aTokenAttributes, $tocToken->[TT_INCLUDE_ATTRIBUTES_BEGIN], 0
 | |
| 				) &&
 | |
| 				HTML::TocGenerator::_doesHashContainHash(
 | |
| 					$aTokenAttributes, $tocToken->[TT_EXCLUDE_ATTRIBUTES_BEGIN], 1
 | |
| 				)
 | |
| 			) {
 | |
| 				# Yes, tag and attributes match;
 | |
| 					# Aliases
 | |
| 				$level	    = $tocToken->[TT_GROUP]{'level'};
 | |
| 				$levelToToc = $tocToken->[TT_TOC]{options}{'levelToToc'};
 | |
| 				$groupId     = $tocToken->[TT_GROUP]{'groupId'}; 
 | |
| 				$groupToToc = $tocToken->[TT_TOC]{options}{'groupToToc'};
 | |
| 					# Must level and group be processed?
 | |
| 				if (
 | |
| 					($level =~ m/$levelToToc/) &&
 | |
| 					($groupId =~ m/$groupToToc/)
 | |
| 				) {
 | |
| 					# Yes, level and group must be processed;
 | |
| 						# Indicate token acts as ToC-starting-token
 | |
| 					$result = 1;
 | |
| 						# Process ToC-starting-token
 | |
| 					$self->_processTocStartingToken(
 | |
| 						$tocToken, $aTokenType, $aTokenAttributes, $aTokenOrigText
 | |
| 					);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 		# Return value
 | |
| 	return $result;
 | |
| }  # _processTokenAsTocStartingToken()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_resetBatchVariables() -------------------------------
 | |
| # function: Reset variables which are set because of batch invocation.
 | |
| 
 | |
| sub _resetBatchVariables {
 | |
| 		# Get arguments
 | |
| 	my ($self) = @_;
 | |
| 
 | |
| 		# Filename of current file being parsed, empty string if not available
 | |
| 	$self->{_currentFile} = "";
 | |
| 		# Arrays containing start, end, comment, text & declaration tokens which 
 | |
| 		# must trigger the ToC assembling.  Each array element may contain a 
 | |
| 		# reference to an array containing the following elements:
 | |
| 		#
 | |
|       #    TT_TAG_BEGIN                => 0;
 | |
|       #    TT_TAG_END                  => 1;
 | |
|       #    TT_TAG_TYPE_END             => 2;
 | |
|       #    TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
 | |
|       #    TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
 | |
|       #    TT_INCLUDE_ATTRIBUTES_END   => 5;
 | |
|       #    TT_EXCLUDE_ATTRIBUTES_END   => 6;
 | |
|       #    TT_GROUP                    => 7;
 | |
|       #    TT_TOC                      => 8;
 | |
| 		#    TT_ATTRIBUTES_TOC           => 9;
 | |
| 		#
 | |
| 	$self->{_tokensTocBegin} = [
 | |
| 		[],  # TT_TOKENTYPE_START      
 | |
| 		[],  # TT_TOKENTYPE_END        
 | |
| 		[],  # TT_TOKENTYPE_COMMENT    
 | |
| 		[],  # TT_TOKENTYPE_TEXT       
 | |
| 		[]   # TT_TOKENTYPE_DECLARATION
 | |
| 	];
 | |
| 	$self->{_tokensTocEnd} = [
 | |
| 		[],  # TT_TOKENTYPE_START      
 | |
| 		[],  # TT_TOKENTYPE_END        
 | |
| 		[],  # TT_TOKENTYPE_COMMENT    
 | |
| 		[],  # TT_TOKENTYPE_TEXT       
 | |
| 		[]   # TT_TOKENTYPE_DECLARATION
 | |
| 	];
 | |
| 		# TRUE if ToCs have been initialized, FALSE if not.
 | |
| 	$self->{_doneInitializeTocs} = 0;
 | |
| 		# Array of ToCs to process
 | |
| 	$self->{_tocs} = [];
 | |
| 		# Active anchor name
 | |
| 	$self->{_activeAnchorName} = undef;
 | |
| }  # _resetBatchVariables()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_resetStackVariables() -------------------------------
 | |
| # function: Reset variables which cumulate during ToC generation.
 | |
| 
 | |
| sub _resetStackVariables {
 | |
| 		# Get arguments
 | |
| 	my ($self) = @_;
 | |
| 		# Reset variables
 | |
| 	$self->{levels}        = undef;
 | |
| 	$self->{groupIdLevels} = undef;
 | |
| }  # _resetStackVariables()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_setActiveAnchorName() -------------------------------
 | |
| # function: Set active anchor name.
 | |
| # args:     - aAnchorName: Name of anchor name to set active.
 | |
| 
 | |
| sub _setActiveAnchorName {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aAnchorName) = @_;
 | |
| 		# Set active anchor name
 | |
| 	$self->{_activeAnchorName} = $aAnchorName;
 | |
| }  # _setActiveAnchorName()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::_showWarning() ---------------------------------------
 | |
| # function: Show warning.
 | |
| # args:     - aWarningNr: Number of warning to show.
 | |
| #           - aWarningArgs: Arguments to display within the warning.
 | |
| 
 | |
| sub _showWarning {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aWarningNr, $aWarningArgs) = @_;
 | |
| 		# Local variables
 | |
| 	my (%warnings);
 | |
| 		# Set warnings
 | |
| 	%warnings = (
 | |
| 		WARNING_NESTED_ANCHOR_PS_WITHIN_PS()               => 
 | |
| 			"Nested anchor '%s' within anchor '%s'.", 
 | |
| 		WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS() =>
 | |
| 			"ToC attribute '%s' not available within token '%s'.",
 | |
| 	);
 | |
| 		# Show warning
 | |
| 	print STDERR "warning ($aWarningNr): " . sprintf($warnings{"$aWarningNr"}, @$aWarningArgs) . "\n";
 | |
| }  # _showWarning()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::anchorId() -------------------------------------------
 | |
| # function: Anchor id processing method.  Leave it up to the descendant to do 
 | |
| #           something useful with it.
 | |
| # args:     - $aAnchorId
 | |
| #           - $aToc: Reference to ToC to which anchorId belongs.
 | |
| 
 | |
| sub anchorId {
 | |
| }  # anchorId()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::anchorNameBegin() ------------------------------------
 | |
| # function: Anchor name begin processing method.  Leave it up to the descendant
 | |
| #           to do something useful with it.
 | |
| # args:     - $aAnchorName
 | |
| #           - $aToc: Reference to ToC to which anchorname belongs.
 | |
| 
 | |
| sub anchorNameBegin {
 | |
| }  # anchorNameBegin()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::anchorNameEnd() --------------------------------------
 | |
| # function: Anchor name end processing method.  Leave it up to the descendant
 | |
| #           to do something useful with it.
 | |
| # args:     - $aAnchorName
 | |
| #           - $aToc: Reference to ToC to which anchorname belongs.
 | |
| 
 | |
| sub anchorNameEnd {
 | |
| }  # anchorNameEnd()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::comment() --------------------------------------------
 | |
| # function: Process comment.
 | |
| # args:     - $aComment: comment text with '<!--' and '-->' tags stripped off.
 | |
| 
 | |
| sub comment {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aComment) = @_;
 | |
| 		# Must a ToC be generated?
 | |
| 	if ($self->{_doGenerateToc}) {
 | |
| 		# Yes, a ToC must be generated
 | |
| 			# Process end tag as ToC-starting-token
 | |
| 		$self->_processTokenAsTocStartingToken(
 | |
| 			TT_TOKENTYPE_COMMENT, $aComment, undef, \$aComment
 | |
| 		);
 | |
| 			# Process end tag as token which ends ToC registration
 | |
| 		$self->_processTokenAsTocEndingToken(
 | |
| 			TT_TOKENTYPE_COMMENT, $aComment
 | |
| 		);
 | |
| 	}
 | |
| }  # comment()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::end() ------------------------------------------------
 | |
| # function: This function is called every time a closing tag is encountered.
 | |
| # args:     - $aTag: tag name (in lower case).
 | |
| #           - $aOrigText: tag name including brackets.
 | |
| 
 | |
| sub end {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTag, $aOrigText) = @_;
 | |
| 		# Local variables
 | |
| 	my ($tag, $toc, $i);
 | |
| 		# Must a ToC be generated?
 | |
| 	if ($self->{_doGenerateToc}) {
 | |
| 		# Yes, a ToC must be generated
 | |
| 			# Process end tag as ToC-starting-token
 | |
| 		$self->_processTokenAsTocStartingToken(
 | |
| 			TT_TOKENTYPE_END, $aTag, undef, \$aOrigText
 | |
| 		);
 | |
| 			# Process end tag as ToC-ending-token
 | |
| 		$self->_processTokenAsTocEndingToken(
 | |
| 			TT_TOKENTYPE_END, $aTag
 | |
| 		);
 | |
| 			# Tag is of type 'anchor'?
 | |
| 		if (defined($self->{_activeAnchorName}) && ($aTag eq "a")) {
 | |
| 			# Yes, tag is of type 'anchor';
 | |
| 				# Reset dirty anchor
 | |
| 			$self->{_activeAnchorName} = undef;
 | |
| 		}
 | |
| 	}
 | |
| }  # end()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::extend() ---------------------------------------------
 | |
| # function: Extend ToCs.
 | |
| # args:     - $aTocs: Reference to array of ToC objects
 | |
| #           - $aString: String to parse.
 | |
| 
 | |
| sub extend {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTocs, $aString) = @_;
 | |
| 		# Initialize TocGenerator batch
 | |
| 	$self->_initializeExtenderBatch($aTocs);
 | |
| 		# Extend ToCs
 | |
| 	$self->_extend($aString);
 | |
| 		# Deinitialize TocGenerator batch
 | |
| 	$self->_deinitializeExtenderBatch();
 | |
| }  # extend()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::extendFromFile() -------------------------------------
 | |
| # function: Extend ToCs.
 | |
| # args:     - @aTocs: Reference to array of ToC objects
 | |
| #           - @aFiles: Reference to array of files to parse.
 | |
| 
 | |
| sub extendFromFile {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTocs, $aFiles) = @_;
 | |
| 		# Initialize TocGenerator batch
 | |
| 	$self->_initializeExtenderBatch($aTocs);
 | |
| 		# Extend ToCs
 | |
| 	$self->_extendFromFile($aFiles);
 | |
| 		# Deinitialize TocGenerator batch
 | |
| 	$self->_deinitializeExtenderBatch();
 | |
| }  # extendFromFile()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::generate() -------------------------------------------
 | |
| # function: Generate ToC.
 | |
| # args:     - $aToc: Reference to (array of) ToC object(s)
 | |
| #           - $aString: Reference to string to parse
 | |
| #           - $aOptions: optional options
 | |
| 
 | |
| sub generate {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aToc, $aString, $aOptions) = @_;
 | |
| 		# Initialize TocGenerator batch
 | |
| 	$self->_initializeGeneratorBatch($aToc, $aOptions);
 | |
| 		# Do generate ToC
 | |
| 	$self->_generate($aString);
 | |
| 		# Deinitialize TocGenerator batch
 | |
| 	$self->_deinitializeGeneratorBatch();
 | |
| }  # generate()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::generateFromFile() -----------------------------------
 | |
| # function: Generate ToC.
 | |
| # args:     - $aToc: Reference to (array of) ToC object(s)
 | |
| #           - $aFile: (reference to array of) file to parse.
 | |
| #           - $aOptions: optional options
 | |
| 
 | |
| sub generateFromFile {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aToc, $aFile, $aOptions) = @_;
 | |
| 		# Initialize TocGenerator batch
 | |
| 	$self->_initializeGeneratorBatch($aToc, $aOptions);
 | |
| 		# Do generate ToC
 | |
| 	$self->_generateFromFile($aFile);
 | |
| 		# Deinitialize TocGenerator batch
 | |
| 	$self->_deinitializeGeneratorBatch();
 | |
| }  # generateFromFile()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::number() ---------------------------------------------
 | |
| # function: Heading number processing method.  Leave it up to the descendant
 | |
| #           to do something useful with it.
 | |
| # args:     - $aNumber
 | |
| #           - $aToc: Reference to ToC to which anchorname belongs.
 | |
| 
 | |
| sub number {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aNumber, $aToc) = @_;
 | |
| }  # number()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::parse() ----------------------------------------------
 | |
| # function: Parse scalar.
 | |
| # args:     - $aString: string to parse
 | |
| 
 | |
| sub parse {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aString) = @_;
 | |
| 		# Call ancestor
 | |
| 	$self->SUPER::parse($aString);
 | |
| }  # parse()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::parse_file() -----------------------------------------
 | |
| # function: Parse file.
 | |
| 
 | |
| sub parse_file {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aFile) = @_;
 | |
| 		# Call ancestor
 | |
| 	$self->SUPER::parse_file($aFile);
 | |
| }  # parse_file()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::setOptions() -----------------------------------------
 | |
| # function: Set options.
 | |
| # args:     - aOptions: Reference to hash containing options.
 | |
| 
 | |
| sub setOptions {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aOptions) = @_;
 | |
| 		# Options are defined?
 | |
| 	if (defined($aOptions)) {
 | |
| 		# Yes, options are defined; add to options
 | |
| 		%{$self->{options}} = (%{$self->{options}}, %$aOptions);
 | |
| 	}
 | |
| }  # setOptions()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::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) = @_;
 | |
| 	$self->{isTocToken} = 0;
 | |
| 		# Start tag is of type 'anchor name'?
 | |
| 	if ($aTag eq "a" && defined($aAttr->{name})) {
 | |
| 		# Yes, start tag is of type 'anchor name';
 | |
| 			# Is another anchor already active?
 | |
| 		if (defined($self->{_activeAnchorName})) {
 | |
| 			# Yes, another anchor is already active;
 | |
| 				# Is the first anchor inserted by 'TocGenerator'?
 | |
| 			if ($self->{_doOutputAnchorNameEnd}) {
 | |
| 				# Yes, the first anchor is inserted by 'TocGenerator';
 | |
| 					# Show warning
 | |
| 				$self->_showWarning(
 | |
| 					WARNING_NESTED_ANCHOR_PS_WITHIN_PS,
 | |
| 					[$aOrigText, $self->{_activeAnchorName}]
 | |
| 				);
 | |
| 			}
 | |
| 		}
 | |
| 			# Set active anchor name
 | |
| 		$self->_setActiveAnchorName($aAttr->{name});
 | |
| 	}
 | |
| 		# Must a ToC be generated?
 | |
| 	if ($self->{_doGenerateToc}) {
 | |
| 		# Yes, a ToC must be generated
 | |
| 			# Process start tag as ToC token
 | |
| 		$self->{isTocToken} = $self->_processTokenAsTocStartingToken(
 | |
| 			TT_TOKENTYPE_START, $aTag, $aAttr, \$aOrigText
 | |
| 		);
 | |
| 			# Process end tag as ToC-ending-token
 | |
| 		$self->_processTokenAsTocEndingToken(
 | |
| 			TT_TOKENTYPE_START, $aTag
 | |
| 		);
 | |
| 	}
 | |
| }  # start()
 | |
| 
 | |
| 
 | |
| #--- HTML::TocGenerator::text() -----------------------------------------------
 | |
| # function: This function is called every time plain text is encountered.
 | |
| # args:     - @_: array containing data.
 | |
| 
 | |
| sub text {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aText) = @_;
 | |
| 		# Local variables
 | |
| 	my ($text, $toc, $i, $token, $tokens);
 | |
| 		# Must a ToC be generated?
 | |
| 	if ($self->{_doGenerateToc}) {
 | |
| 		# Yes, a ToC must be generated
 | |
| 			# Are there dirty start tags?
 | |
| 
 | |
| 			# Loop through token types
 | |
| 		foreach $tokens (@{$self->{_tokensTocEnd}}) {
 | |
| 				# Loop though tokens
 | |
| 			foreach $token (@$tokens) {
 | |
| 					# Add text to toc
 | |
| 
 | |
| 					# Alias
 | |
| 				$toc = $token->[TT_TOC];
 | |
| 					# Remove possible newlines from text
 | |
| 				($text = $aText) =~ s/\s*\n\s*/ /g;
 | |
| 					# Add text to toc
 | |
| 				$self->_processTocText($text, $toc);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }  # text()
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #=== HTML::_TokenTocParser ====================================================
 | |
| # function: Parse 'toc tokens'.  'Toc tokens' mark HTML code which is to be
 | |
| #           inserted into the ToC.
 | |
| # note:     Used internally.
 | |
| 
 | |
| package HTML::_TokenTocParser;
 | |
| 
 | |
| 
 | |
| BEGIN {
 | |
| 	use vars qw(@ISA);
 | |
| 
 | |
| 	@ISA = qw(HTML::Parser);
 | |
| }
 | |
| 
 | |
| 
 | |
| END {}
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocParser::new() ---------------------------------------------
 | |
| # function: Constructor
 | |
| 
 | |
| sub new {
 | |
| 		# Get arguments
 | |
| 	my ($aType) = @_;
 | |
| 		# Create instance
 | |
| 	my $self = $aType->SUPER::new;
 | |
| 
 | |
| 		# Return instance
 | |
| 	return $self;
 | |
| }  # new()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocParser::_parseAttributes() --------------------------------
 | |
| # function: Parse attributes.
 | |
| # args:     - $aAttr: Reference to hash containing all tag attributes (in lower
 | |
| #                case).
 | |
| #           - $aIncludeAttributes: Reference to hash to which 'include
 | |
| #                attributes' must be added.
 | |
| #           - $aExcludeAttributes: Reference to hash to which 'exclude
 | |
| #                attributes' must be added.
 | |
| #           - $aTocAttributes: Reference to hash to which 'ToC attributes' 
 | |
| #                must be added.
 | |
| 
 | |
| sub _parseAttributes {
 | |
| 		# Get arguments
 | |
| 	my (
 | |
| 		$self, $aAttr, $aIncludeAttributes, $aExcludeAttributes,
 | |
| 		$aTocAttributes
 | |
| 	) = @_;
 | |
| 		# Local variables
 | |
| 	my ($key, $value);
 | |
| 	my ($attributeToExcludeToken, $attributeToTocToken);
 | |
| 		# Get token which marks attributes which must be excluded
 | |
| 	$attributeToExcludeToken = $self->{_toc}{options}{'attributeToExcludeToken'};
 | |
| 	$attributeToTocToken     = $self->{_toc}{options}{'attributeToTocToken'};
 | |
| 		# Loop through attributes
 | |
| 	while (($key, $value) = each %$aAttr) {
 | |
| 			# Attribute value equals 'ToC token'?
 | |
| 		if ($value =~ m/$attributeToTocToken/) {
 | |
| 			# Yes, attribute value equals 'ToC token';
 | |
| 				# Add attribute to 'ToC attributes'
 | |
| 			push @$aTocAttributes, $key;
 | |
| 		}
 | |
| 		else {
 | |
| 			# No, attribute isn't 'ToC' token;
 | |
| 				# Attribute value starts with 'exclude token'?
 | |
| 			if ($value =~ m/^$attributeToExcludeToken(.*)/) {
 | |
| 				# Yes, attribute value starts with 'exclude token';
 | |
| 					# Add attribute to 'exclude attributes'
 | |
| 				$$aExcludeAttributes{$key} = "$1";
 | |
| 			}
 | |
| 			else {
 | |
| 				# No, attribute key doesn't start with '-';
 | |
| 					# Add attribute to 'include attributes'
 | |
| 				$$aIncludeAttributes{$key} = $value;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }  # _parseAttributes()
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #=== HTML::_TokenTocBeginParser ===============================================
 | |
| # function: Parse 'toc tokens'.  'Toc tokens' mark HTML code which is to be
 | |
| #           inserted into the ToC.
 | |
| # note:     Used internally.
 | |
| 
 | |
| package HTML::_TokenTocBeginParser;
 | |
| 
 | |
| 
 | |
| BEGIN {
 | |
| 	use vars qw(@ISA);
 | |
| 
 | |
| 	@ISA = qw(HTML::_TokenTocParser);
 | |
| }
 | |
| 
 | |
| END {}
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocBeginParser::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::_TokenTocBeginParser::_processAttributes() -------------------------
 | |
| # function: Process attributes.
 | |
| # args:     - $aAttributes: Attributes to parse.
 | |
| 
 | |
| sub _processAttributes {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aAttributes) = @_;
 | |
| 		# Local variables
 | |
| 	my (%includeAttributes, %excludeAttributes, @tocAttributes);
 | |
| 
 | |
| 		# Parse attributes
 | |
| 	$self->_parseAttributes(
 | |
| 		$aAttributes, \%includeAttributes, \%excludeAttributes, \@tocAttributes
 | |
| 	);
 | |
| 		# Include attributes are specified?
 | |
| 	if (keys(%includeAttributes) > 0) {
 | |
| 		# Yes, include attributes are specified;
 | |
| 			# Store include attributes
 | |
| 		@${$self->{_lastAddedToken}}[
 | |
| 			HTML::TocGenerator::TT_INCLUDE_ATTRIBUTES_BEGIN
 | |
| 		] = \%includeAttributes;
 | |
| 	}
 | |
| 		# Exclude attributes are specified?
 | |
| 	if (keys(%excludeAttributes) > 0) {
 | |
| 		# Yes, exclude attributes are specified;
 | |
| 			# Store exclude attributes
 | |
| 		@${$self->{_lastAddedToken}}[
 | |
| 			HTML::TocGenerator::TT_EXCLUDE_ATTRIBUTES_BEGIN
 | |
| 		] = \%excludeAttributes;
 | |
| 	}
 | |
| 		# Toc attributes are specified?
 | |
| 	if (@tocAttributes > 0) {
 | |
| 		# Yes, toc attributes are specified;
 | |
| 			# Store toc attributes
 | |
| 		@${$self->{_lastAddedToken}}[
 | |
| 			HTML::TocGenerator::TT_ATTRIBUTES_TOC
 | |
| 		] = \@tocAttributes;
 | |
| 	}
 | |
| }  # _processAttributes()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocBeginParser::_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::TocGenerator::TT_TAG_BEGIN] = $aTag;
 | |
| 	$$tokenArray[$index][HTML::TocGenerator::TT_GROUP]     = $self->{_group};
 | |
| 	$$tokenArray[$index][HTML::TocGenerator::TT_TOC]       = $self->{_toc};
 | |
| }  # _processToken()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocBeginParser::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::_TokenTocBeginParser::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::_TokenTocBeginParser::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::_TokenTocBeginParser::parse() --------------------------------------
 | |
| # function: Parse begin token.
 | |
| # args:     - $aToken: 'toc token' to parse
 | |
| 
 | |
| sub parse {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aString) = @_;
 | |
| 		# Call ancestor
 | |
| 	$self->SUPER::parse($aString);
 | |
| }  # parse()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocBeginParser->setGroup() -----------------------------------
 | |
| # function: Set current 'tokenToToc' group.
 | |
| 
 | |
| sub setGroup {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aGroup) = @_;
 | |
| 		# Set current 'tokenToToc' group
 | |
| 	$self->{_group} = $aGroup;
 | |
| }  # setGroup()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocBeginParser->setToc() -------------------------------------
 | |
| # function: Set current ToC.
 | |
| 
 | |
| sub setToc {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aToc) = @_;
 | |
| 		# Set current ToC
 | |
| 	$self->{_toc} = $aToc;
 | |
| }  # setToc()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocBeginParser::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::_TokenTocBeginParser::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()
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #=== HTML::_TokenTocEndParser =================================================
 | |
| # function: Parse 'toc tokens'.  'Toc tokens' mark HTML code which is to be
 | |
| #           inserted into the ToC.
 | |
| # note:     Used internally.
 | |
| 
 | |
| package HTML::_TokenTocEndParser;
 | |
| 
 | |
| 
 | |
| BEGIN {
 | |
| 	use vars qw(@ISA);
 | |
| 
 | |
| 	@ISA = qw(HTML::_TokenTocParser);
 | |
| }
 | |
| 
 | |
| 
 | |
| END {}
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocEndParser::new() ------------------------------------------
 | |
| # function: Constructor
 | |
| # args:     - $aType: Class type.
 | |
| 
 | |
| sub new {
 | |
| 		# Get arguments
 | |
| 	my ($aType) = @_;
 | |
| 		# Create instance
 | |
| 	my $self = $aType->SUPER::new;
 | |
| 		# Reference to last added token
 | |
| 	$self->{_lastAddedToken} = undef;
 | |
| 		# Return instance
 | |
| 	return $self;
 | |
| }  # new()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocEndParser::_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->{_Token}}[
 | |
| 			HTML::TocGenerator::TT_INCLUDE_ATTRIBUTES_END
 | |
| 		] = \%includeAttributes;
 | |
| 	}
 | |
| 		# Exclude attributes are specified?
 | |
| 	if (keys(%excludeAttributes) > 0) {
 | |
| 		# Yes, exclude attributes are specified;
 | |
| 			# Store exclude attributes
 | |
| 		@${$self->{_Token}}[
 | |
| 			HTML::TocGenerator::TT_EXCLUDE_ATTRIBUTES_END
 | |
| 		] = \%excludeAttributes;
 | |
| 	}
 | |
| }  # _processAttributes()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocEndParser::_processToken() --------------------------------
 | |
| # function: Process token.
 | |
| # args:     - $aTokenType: Type of token to process.
 | |
| #           - $aTag: Tag of token.
 | |
| 
 | |
| sub _processToken {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aTokenType, $aTag) = @_;
 | |
| 		# Update token
 | |
| 	@${$self->{_token}}[HTML::TocGenerator::TT_TAG_TYPE_END] = $aTokenType;
 | |
| 	@${$self->{_token}}[HTML::TocGenerator::TT_TAG_END]      = $aTag;
 | |
| 		# Indicate token type which has been processed
 | |
| 	$self->{_lastAddedTokenType} = $aTokenType;
 | |
| }  # _processToken()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocEndParser::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::_TokenTocDeclarationParser::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::_TokenTocEndParser::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::_TokenTocEndParser::parse() ----------------------------------------
 | |
| # function: Parse token.
 | |
| # args:     - $aString: 'toc token' to parse
 | |
| #           - $aToken: Reference to token
 | |
| #           - $aTokenTypeBegin: Type of begin token
 | |
| 
 | |
| sub parse {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aString, $aToken, $aTokenTypeBegin) = @_;
 | |
| 		# Token argument specified?
 | |
| 	if (defined($aToken)) {
 | |
| 		# Yes, token argument is specified;
 | |
| 			# Store token reference
 | |
| 		$self->{_token} = $aToken;
 | |
| 	}
 | |
| 		# End tag defined?
 | |
| 	if (! defined($aString)) {
 | |
| 		# No, end tag isn't defined;
 | |
| 			# Last added tokentype was of type 'start'?
 | |
| 		if (
 | |
| 			(defined($aTokenTypeBegin)) &&
 | |
| 			($aTokenTypeBegin == HTML::TocGenerator::TT_TOKENTYPE_START) 
 | |
| 		) {
 | |
| 			# Yes, last added tokentype was of type 'start';
 | |
| 				# Assume end tag
 | |
| 			$self->_processToken(
 | |
| 				HTML::TocGenerator::TT_TAG_END,
 | |
| 				@${$self->{_token}}[HTML::TocGenerator::TT_TAG_BEGIN]
 | |
| 			);
 | |
| 		}
 | |
| 	}
 | |
| 	else {
 | |
| 			# Call ancestor
 | |
| 		$self->SUPER::parse($aString);
 | |
| 	}
 | |
| }  # parse()
 | |
| 
 | |
| 
 | |
| #--- HTML::_TokenTocEndParser::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::_TokenTocEndParser::text() -----------------------------------------
 | |
| # function: This function is called every time plain text is encountered.
 | |
| # args:     - @_: array containing data.
 | |
| 
 | |
| sub text {
 | |
| 		# Get arguments
 | |
| 	my ($self, $aText) = @_;
 | |
| 
 | |
| 		# Is token already created?
 | |
| 	if (defined($self->{_lastAddedTokenType})) {
 | |
| 		# Yes, token is already created;
 | |
| 			# Add tag to existing token
 | |
| 		@${$self->{_token}}[HTML::TocGenerator::TT_TAG_END] .= $aText;
 | |
| 	}
 | |
| 	else {
 | |
| 		# No, token isn't created;
 | |
| 			# Process token
 | |
| 		$self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
 | |
| 	}
 | |
| }  # text()
 | |
| 
 | |
| 
 | |
| 1;
 | 
