############################################################################### # # 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-2008 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() . "\n\n\n" . $self->BuildContent($sourceFile, $parsedFile) . "\n\n\n" . $self->BuildFooter() . "\n\n\n" . $self->BuildMenu($sourceFile, undef) . "\n\n\n" . $self->BuildToolTips() . "\n\n\n" . '
' . '' . 'Close' . '
' . "\n\n\n" . $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 $startIndexPage = '' . "\n\n" . '' . (NaturalDocs::Settings->CharSet() ? '' : '') . '' . $indexTitle; if (defined NaturalDocs::Menu->Title()) { $startIndexPage .= ' - ' . $self->StringToHTML(NaturalDocs::Menu->Title()); }; $startIndexPage .= '' . '' . '' . '' . '' . $self->OpeningBrowserStyles() . $self->StandardComments() . "\n\n\n" . '
' . '
' . $indexTitle . '
'; my $endIndexPage = '
' . "\n\n\n" . $self->BuildFooter() . "\n\n\n" . $self->BuildMenu(undef, $type) . "\n\n\n" . '
' . '' . 'Close' . '
' . "\n\n\n" . $self->ClosingBrowserStyles() . ''; my $startSearchResultsPage = '' . "\n\n" . '' . (NaturalDocs::Settings->CharSet() ? '' : '') . '' . '' . '' . $self->OpeningBrowserStyles() . $self->StandardComments() . "\n\n\n" . '
'; my $endSearchResultsPage = '
' . $self->ClosingBrowserStyles() . ''; my $indexContent = NaturalDocs::SymbolTable->Index($type); my $pageCount = $self->BuildIndexPages($type, $indexContent, $startIndexPage, $endIndexPage, $startSearchResultsPage, $endSearchResultsPage); $self->PurgeIndexFiles($type, $indexContent, $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 . # # Dependencies: # # - Requires to surround its content with the exact strings "". # - Requires to surround its content with the exact strings "". # 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/