############################################################################### # # Package: NaturalDocs::Builder::HTML # ############################################################################### # # A package that generates output in HTML. # # All functions are called with Package->Function() notation. # ############################################################################### # This file is part of Natural Docs, which is Copyright (C) 2003-2005 Greg Valure # Natural Docs is licensed under the GPL use strict; use integer; package NaturalDocs::Builder::HTML; use base 'NaturalDocs::Builder::HTMLBase'; ############################################################################### # Group: Implemented Interface Functions # # Function: INIT # # Registers the package with . # sub INIT { NaturalDocs::Builder->Add(__PACKAGE__); }; # # Function: CommandLineOption # # Returns the option to follow -o to use this package. In this case, "html". # sub CommandLineOption { return 'HTML'; }; # # Function: BuildFile # # Builds the output file from the parsed source file. # # Parameters: # # sourcefile - The of the source file. # parsedFile - An arrayref of the source file as objects. # sub BuildFile #(sourceFile, parsedFile) { my ($self, $sourceFile, $parsedFile) = @_; my $outputFile = $self->OutputFileOf($sourceFile); # 99.99% of the time the output directory will already exist, so this will actually be more efficient. It only won't exist # if a new file was added in a new subdirectory and this is the first time that file was ever parsed. if (!open(OUTPUTFILEHANDLE, '>' . $outputFile)) { NaturalDocs::File->CreatePath( NaturalDocs::File->NoFileName($outputFile) ); open(OUTPUTFILEHANDLE, '>' . $outputFile) or die "Couldn't create output file " . $outputFile . "\n"; }; print OUTPUTFILEHANDLE '' . "\n\n" . '' . (NaturalDocs::Settings->CharSet() ? '' : '') . '' . $self->BuildTitle($sourceFile) . '' . '' . '' . '' . $self->OpeningBrowserStyles() . $self->StandardComments() # I originally had this part done in CSS, but there were too many problems. Back to good old HTML tables. . '' . '' . "\n\n" . '' . "\n\n" . '
' . $self->BuildContent($sourceFile, $parsedFile) . '
' . '' . $self->BuildToolTips() . $self->ClosingBrowserStyles() . ''; close(OUTPUTFILEHANDLE); }; # # Function: BuildIndex # # Builds an index for the passed type. # # Parameters: # # type - The to limit the index to, or undef if none. # sub BuildIndex #(type) { my ($self, $type) = @_; my $indexTitle = $self->IndexTitleOf($type); my $indexFile = $self->IndexFileOf($type); my $startPage = '' . "\n\n" . '' . (NaturalDocs::Settings->CharSet() ? '' : '') . '' . $indexTitle; if (defined NaturalDocs::Menu->Title()) { $startPage .= ' - ' . $self->StringToHTML(NaturalDocs::Menu->Title()); }; $startPage .= '' . '' . '' . '' . $self->OpeningBrowserStyles() . $self->StandardComments() # I originally had this part done in CSS, but there were too many problems. Back to good old HTML tables. . '' . '' . '' . '
' . '
' . $indexTitle . '
'; my $endPage = '
' . '' . $self->ClosingBrowserStyles() . ''; my $pageCount = $self->BuildIndexPages($type, NaturalDocs::SymbolTable->Index($type), $startPage, $endPage); $self->PurgeIndexFiles($type, $pageCount + 1); }; # # Function: UpdateMenu # # Updates the menu in all the output files that weren't rebuilt. Also generates index.html. # sub UpdateMenu { my $self = shift; # Update the menu on unbuilt files. my $filesToUpdate = NaturalDocs::Project->UnbuiltFilesWithContent(); foreach my $sourceFile (keys %$filesToUpdate) { $self->UpdateFile($sourceFile); }; # Update the menu on unchanged index files. my $indexes = NaturalDocs::Menu->Indexes(); foreach my $index (keys %$indexes) { if (!NaturalDocs::SymbolTable->IndexChanged($index)) { $self->UpdateIndex($index); }; }; # Update index.html my $firstMenuEntry = $self->FindFirstFile(); my $indexFile = NaturalDocs::File->JoinPaths( NaturalDocs::Settings->OutputDirectoryOf($self), 'index.html' ); # We have to check because it's possible that there may be no files with Natural Docs content and thus no files on the menu. if (defined $firstMenuEntry) { open(INDEXFILEHANDLE, '>' . $indexFile) or die "Couldn't create output file " . $indexFile . ".\n"; print INDEXFILEHANDLE '' . '' . ''; close INDEXFILEHANDLE; } elsif (-e $indexFile) { unlink($indexFile); }; }; ############################################################################### # Group: Support Functions # # Function: UpdateFile # # Updates an output file. Replaces the menu, HTML title, and footer. It opens the output file, makes the changes, and saves it # back to disk, which is much quicker than rebuilding the file from scratch if these were the only things that changed. # # Parameters: # # sourceFile - The source . # sub UpdateFile #(sourceFile) { my ($self, $sourceFile) = @_; my $outputFile = $self->OutputFileOf($sourceFile); if (open(OUTPUTFILEHANDLE, '<' . $outputFile)) { my $content; read(OUTPUTFILEHANDLE, $content, -s OUTPUTFILEHANDLE); close(OUTPUTFILEHANDLE); $content =~ s{[^<]*<\/title>}{'<title>' . $self->BuildTitle($sourceFile) . ''}e; $content =~ s/.*?/$self->BuildMenu($sourceFile, undef, undef)/es; $content =~ s/.*?/$self->BuildFooter()/e; open(OUTPUTFILEHANDLE, '>' . $outputFile); print OUTPUTFILEHANDLE $content; close(OUTPUTFILEHANDLE); }; }; # # Function: UpdateIndex # # Updates an index's output file. Replaces the menu and footer. It opens the output file, makes the changes, and saves it # back to disk, which is much quicker than rebuilding the file from scratch if these were the only things that changed. # # Parameters: # # type - The index , or undef if none. # sub UpdateIndex #(type) { my ($self, $type) = @_; my $page = 1; my $outputFile = $self->IndexFileOf($type, $page); my $newMenu = $self->BuildMenu(undef, $type, undef); my $newFooter = $self->BuildFooter(); while (-e $outputFile) { open(OUTPUTFILEHANDLE, '<' . $outputFile) or die "Couldn't open output file " . $outputFile . ".\n"; my $content; read(OUTPUTFILEHANDLE, $content, -s OUTPUTFILEHANDLE); close(OUTPUTFILEHANDLE); $content =~ s/.*?/$newMenu/es; $content =~ s/