From 61bfe2d70cae6be8c4086a210a5451135ccca9ea Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Sat, 2 Aug 2008 08:21:29 +0000 Subject: added doc tool --- docs/tool/Modules/NaturalDocs/Builder/HTMLBase.pm | 3693 +++++++++++++++++++++ 1 file changed, 3693 insertions(+) create mode 100644 docs/tool/Modules/NaturalDocs/Builder/HTMLBase.pm (limited to 'docs/tool/Modules/NaturalDocs/Builder/HTMLBase.pm') diff --git a/docs/tool/Modules/NaturalDocs/Builder/HTMLBase.pm b/docs/tool/Modules/NaturalDocs/Builder/HTMLBase.pm new file mode 100644 index 00000000..d943622b --- /dev/null +++ b/docs/tool/Modules/NaturalDocs/Builder/HTMLBase.pm @@ -0,0 +1,3693 @@ +############################################################################### +# +# Package: NaturalDocs::Builder::HTMLBase +# +############################################################################### +# +# A base package for all the shared functionality in and +# . +# +############################################################################### + +# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure +# Natural Docs is licensed under the GPL + + +use Tie::RefHash; + +use strict; +use integer; + +package NaturalDocs::Builder::HTMLBase; + +use base 'NaturalDocs::Builder::Base'; + +use NaturalDocs::DefineMembers 'MADE_EMPTY_SEARCH_RESULTS_PAGE', 'MadeEmptySearchResultsPage()', + 'SetMadeEmptySearchResultsPage()'; + + + +############################################################################### +# Group: Object Variables + + +# +# Constants: Members +# +# The object is implemented as a blessed arrayref, with the follow constants as indexes. +# +# MADE_EMPTY_SEARCH_RESULTS_PAGE - Whether the search results page for searches with no results was generated. +# + +# +# Constants: NDMarkupToHTML Styles +# +# These are the styles used with . +# +# NDMARKUPTOHTML_GENERAL - General style. +# NDMARKUPTOHTML_SUMMARY - For summaries. +# NDMARKUPTOHTML_TOOLTIP - For tooltips. +# +use constant NDMARKUPTOHTML_GENERAL => undef; +use constant NDMARKUPTOHTML_SUMMARY => 1; +use constant NDMARKUPTOHTML_TOOLTIP => 2; + + + +############################################################################### +# Group: Package Variables +# These variables are shared by all instances of the package so don't change them. + + +# +# handle: FH_CSS_FILE +# +# The file handle to use when updating CSS files. +# + + +# +# Hash: abbreviations +# +# An existence hash of acceptable abbreviations. These are words that won't put a second space +# after when followed by period-whitespace-capital letter. Yes, this is seriously over-engineered. +# +my %abbreviations = ( mr => 1, mrs => 1, ms => 1, dr => 1, + rev => 1, fr => 1, 'i.e' => 1, + maj => 1, gen => 1, pres => 1, sen => 1, rep => 1, + n => 1, s => 1, e => 1, w => 1, ne => 1, se => 1, nw => 1, sw => 1 ); + +# +# array: indexHeadings +# +# An array of the headings of all the index sections. First is for symbols, second for numbers, and the rest for each letter. +# +my @indexHeadings = ( '$#!', '0-9', 'A' .. 'Z' ); + +# +# array: indexAnchors +# +# An array of the HTML anchors of all the index sections. First is for symbols, second for numbers, and the rest for each letter. +# +my @indexAnchors = ( 'Symbols', 'Numbers', 'A' .. 'Z' ); + +# +# array: searchExtensions +# +# An array of the search file name extensions for all the index sections. First is for symbols, second for numbers, and the rest +# for each letter. +# +my @searchExtensions = ( 'Symbols', 'Numbers', 'A' .. 'Z' ); + +# +# bool: saidUpdatingCSSFile +# +# Whether the status message "Updating CSS file..." has been displayed. We only want to print it once, no matter how many +# HTML-based targets we are building. +# +my $saidUpdatingCSSFile; + +# +# constant: ADD_HIDDEN_BREAKS +# +# Just a synonym for "1" so that setting the flag on is clearer in the calling code. +# +use constant ADD_HIDDEN_BREAKS => 1; + + +############################################################################### +# Group: ToolTip Package Variables +# +# These variables are for the tooltip generation functions only. Since they're reset on every call to and +# , and are only used by them and their support functions, they can be shared by all instances of the +# package. + +# +# int: tooltipLinkNumber +# +# A number used as part of the ID for each link that has a tooltip. Should be incremented whenever one is made. +# +my $tooltipLinkNumber; + +# +# int: tooltipNumber +# +# A number used as part of the ID for each tooltip. Should be incremented whenever one is made. +# +my $tooltipNumber; + +# +# hash: tooltipSymbolsToNumbers +# +# A hash that maps the tooltip symbols to their assigned numbers. +# +my %tooltipSymbolsToNumbers; + +# +# string: tooltipHTML +# +# The generated tooltip HTML. +# +my $tooltipHTML; + + +############################################################################### +# Group: Menu Package Variables +# +# These variables are for the menu generation functions only. Since they're reset on every call to and are +# only used by it and its support functions, they can be shared by all instances of the package. +# + + +# +# hash: prebuiltMenus +# +# A hash that maps output directonies to menu HTML already built for it. There will be no selection or JavaScript in the menus. +# +my %prebuiltMenus; + + +# +# bool: menuNumbersAndLengthsDone +# +# Set when the variables that only need to be calculated for the menu once are done. This includes , +# , , and , and . +# +my $menuNumbersAndLengthsDone; + + +# +# int: menuGroupNumber +# +# The current menu group number. Each time a group is created, this is incremented so that each one will be unique. +# +my $menuGroupNumber; + + +# +# int: menuLength +# +# The length of the entire menu, fully expanded. The value is computed from the . +# +my $menuLength; + + +# +# hash: menuGroupLengths +# +# A hash of the length of each group, *not* including any subgroup contents. The keys are references to each groups' +# object, and the values are their lengths computed from the . +# +my %menuGroupLengths; +tie %menuGroupLengths, 'Tie::RefHash'; + + +# +# hash: menuGroupNumbers +# +# A hash of the number of each group, as managed by . The keys are references to each groups' +# object, and the values are the number. +# +my %menuGroupNumbers; +tie %menuGroupNumbers, 'Tie::RefHash'; + + +# +# int: menuRootLength +# +# The length of the top-level menu entries without expansion. The value is computed from the . +# +my $menuRootLength; + + +# +# constants: Menu Length Constants +# +# Constants used to approximate the lengths of the menu or its groups. +# +# MENU_TITLE_LENGTH - The length of the title. +# MENU_SUBTITLE_LENGTH - The length of the subtitle. +# MENU_FILE_LENGTH - The length of one file entry. +# MENU_GROUP_LENGTH - The length of one group entry. +# MENU_TEXT_LENGTH - The length of one text entry. +# MENU_LINK_LENGTH - The length of one link entry. +# +# MENU_LENGTH_LIMIT - The limit of the menu's length. If the total length surpasses this limit, groups that aren't required +# to be open to show the selection will default to closed on browsers that support it. +# +use constant MENU_TITLE_LENGTH => 3; +use constant MENU_SUBTITLE_LENGTH => 1; +use constant MENU_FILE_LENGTH => 1; +use constant MENU_GROUP_LENGTH => 2; # because it's a line and a blank space +use constant MENU_TEXT_LENGTH => 1; +use constant MENU_LINK_LENGTH => 1; +use constant MENU_INDEX_LENGTH => 1; + +use constant MENU_LENGTH_LIMIT => 35; + + +############################################################################### +# Group: Image Package Variables +# +# These variables are for the image generation functions only. Since they're reset on every call to , +# and are only used by it and its support functions, they can be shared by all instances of thepackage. + + +# +# var: imageAnchorNumber +# Incremented for each image link in the file that requires an anchor. +# +my $imageAnchorNumber; + + +# +# var: imageContent +# +# The actual embedded image HTML for all image links. When generating an image link, the link HTML is returned and +# the HTML for the target image is added here. Periodically, such as after the end of the paragraph, this content should +# be added to the page and the variable set to undef. +# +my $imageContent; + + + +############################################################################### +# Group: Search Package Variables +# +# These variables are for the search generation functions only. Since they're reset on every call to and +# are only used by them and their support functions, they can be shared by all instances of the package. + + +# +# hash: searchResultIDs +# +# A hash mapping lowercase-only search result IDs to the number of times they've been used. This is to work around an IE +# bug where it won't correctly reference IDs if they differ only in case. +# +my %searchResultIDs; + + + +############################################################################### +# Group: Object Functions + + +# +# Function: New +# Creates and returns a new object. +# +sub New + { + my $class = shift; + + my $object = $class->SUPER::New(); + $object->SetMadeEmptySearchResultsPage(0); + + return $object; + }; + + +# Function: MadeEmptySearchResultsPage +# Returns whether the empty search results page was created or not. + +# Function: SetMadeEmptySearchResultsPage +# Sets whether the empty search results page was created or not. + + + +############################################################################### +# Group: Implemented Interface Functions +# +# The behavior of these functions is shared between HTML output formats. +# + + +# +# Function: UpdateImage +# +# Define this function to add or update the passed image in the output. +# +# Parameters: +# +# file - The image +# +sub UpdateImage #(file) + { + my ($self, $file) = @_; + + my $outputFile = $self->OutputImageOf($file); + my $outputDirectory = NaturalDocs::File->NoFileName($outputFile); + + if (!-d $outputDirectory) + { NaturalDocs::File->CreatePath($outputDirectory); }; + + NaturalDocs::File->Copy($file, $outputFile); + }; + + +# +# Function: PurgeFiles +# +# Deletes the output files associated with the purged source files. +# +sub PurgeFiles #(filesToPurge) + { + my ($self, $filesToPurge) = @_; + + # Combine directories into a hash to remove duplicate work. + my %directoriesToPurge; + + foreach my $file (keys %$filesToPurge) + { + # It's possible that there may be files there that aren't in a valid input directory anymore. They won't generate an output + # file name so we need to check for undef. + my $outputFile = $self->OutputFileOf($file); + if (defined $outputFile) + { + unlink($outputFile); + $directoriesToPurge{ NaturalDocs::File->NoFileName($outputFile) } = 1; + }; + }; + + foreach my $directory (keys %directoriesToPurge) + { + NaturalDocs::File->RemoveEmptyTree($directory, NaturalDocs::Settings->OutputDirectoryOf($self)); + }; + }; + + +# +# Function: PurgeIndexes +# +# Deletes the output files associated with the purged source files. +# +# Parameters: +# +# indexes - An existence hashref of the index types to purge. The keys are the or * for the general index. +# +sub PurgeIndexes #(indexes) + { + my ($self, $indexes) = @_; + + foreach my $index (keys %$indexes) + { + $self->PurgeIndexFiles($index, undef, undef); + }; + }; + + +# +# Function: PurgeImages +# +# Define this function to make the package remove all output related to the passed image files. These files are no longer used +# by the documentation. +# +# Parameters: +# +# files - An existence hashref of the image to purge. +# +sub PurgeImages #(files) + { + my ($self, $filesToPurge) = @_; + + # Combine directories into a hash to remove duplicate work. + my %directoriesToPurge; + + foreach my $file (keys %$filesToPurge) + { + # It's possible that there may be files there that aren't in a valid input directory anymore. They won't generate an output + # file name so we need to check for undef. + my $outputFile = $self->OutputImageOf($file); + if (defined $outputFile) + { + unlink($outputFile); + $directoriesToPurge{ NaturalDocs::File->NoFileName($outputFile) } = 1; + }; + }; + + foreach my $directory (keys %directoriesToPurge) + { + NaturalDocs::File->RemoveEmptyTree($directory, NaturalDocs::Settings->OutputDirectoryOf($self)); + }; + }; + + +# +# Function: BeginBuild +# +# Creates the necessary subdirectories in the output directory. +# +sub BeginBuild #(hasChanged) + { + my ($self, $hasChanged) = @_; + + foreach my $directory ( $self->JavaScriptDirectory(), $self->CSSDirectory(), $self->IndexDirectory(), + $self->SearchResultsDirectory() ) + { + if (!-d $directory) + { NaturalDocs::File->CreatePath($directory); }; + }; + }; + + +# +# Function: EndBuild +# +# Synchronizes the projects CSS and JavaScript files. Also generates the search data JavaScript file. +# +sub EndBuild #(hasChanged) + { + my ($self, $hasChanged) = @_; + + + # Update the style sheets. + + my $styles = NaturalDocs::Settings->Styles(); + my $changed; + + my $cssDirectory = $self->CSSDirectory(); + my $mainCSSFile = $self->MainCSSFile(); + + for (my $i = 0; $i < scalar @$styles; $i++) + { + my $outputCSSFile; + + if (scalar @$styles == 1) + { $outputCSSFile = $mainCSSFile; } + else + { $outputCSSFile = NaturalDocs::File->JoinPaths($cssDirectory, ($i + 1) . '.css'); }; + + + my $masterCSSFile = NaturalDocs::File->JoinPaths( NaturalDocs::Settings->ProjectDirectory(), $styles->[$i] . '.css' ); + + if (! -e $masterCSSFile) + { $masterCSSFile = NaturalDocs::File->JoinPaths( NaturalDocs::Settings->StyleDirectory(), $styles->[$i] . '.css' ); }; + + # We check both the date and the size in case the user switches between two styles which just happen to have the same + # date. Should rarely happen, but it might. + if (! -e $outputCSSFile || + (stat($masterCSSFile))[9] != (stat($outputCSSFile))[9] || + -s $masterCSSFile != -s $outputCSSFile) + { + if (!NaturalDocs::Settings->IsQuiet() && !$saidUpdatingCSSFile) + { + print "Updating CSS file...\n"; + $saidUpdatingCSSFile = 1; + }; + + NaturalDocs::File->Copy($masterCSSFile, $outputCSSFile); + + $changed = 1; + }; + }; + + + my $deleteFrom; + + if (scalar @$styles == 1) + { $deleteFrom = 1; } + else + { $deleteFrom = scalar @$styles + 1; }; + + for (;;) + { + my $file = NaturalDocs::File->JoinPaths($cssDirectory, $deleteFrom . '.css'); + + if (! -e $file) + { last; }; + + unlink ($file); + $deleteFrom++; + + $changed = 1; + }; + + + if ($changed) + { + if (scalar @$styles > 1) + { + open(FH_CSS_FILE, '>' . $mainCSSFile); + + for (my $i = 0; $i < scalar @$styles; $i++) + { + print FH_CSS_FILE '@import URL("' . ($i + 1) . '.css");' . "\n"; + }; + + close(FH_CSS_FILE); + }; + }; + + + + # Update the JavaScript files + + my $jsMaster = NaturalDocs::File->JoinPaths( NaturalDocs::Settings->JavaScriptDirectory(), 'NaturalDocs.js' ); + my $jsOutput = $self->MainJavaScriptFile(); + + # We check both the date and the size in case the user switches between two styles which just happen to have the same + # date. Should rarely happen, but it might. + if (! -e $jsOutput || + (stat($jsMaster))[9] != (stat($jsOutput))[9] || + -s $jsMaster != -s $jsOutput) + { + NaturalDocs::File->Copy($jsMaster, $jsOutput); + }; + + + my @indexes = keys %{NaturalDocs::Menu->Indexes()}; + + open(FH_INDEXINFOJS, '>' . NaturalDocs::File->JoinPaths( $self->JavaScriptDirectory(), 'searchdata.js')); + + print FH_INDEXINFOJS + "var indexSectionsWithContent = {\n"; + + for (my $i = 0; $i < scalar @indexes; $i++) + { + if ($i != 0) + { print FH_INDEXINFOJS ",\n"; }; + + print FH_INDEXINFOJS ' "' . NaturalDocs::Topics->NameOfType($indexes[$i], 1, 1) . "\": {\n"; + + my $content = NaturalDocs::SymbolTable->IndexSectionsWithContent($indexes[$i]); + for (my $contentIndex = 0; $contentIndex < 28; $contentIndex++) + { + if ($contentIndex != 0) + { print FH_INDEXINFOJS ",\n"; }; + + print FH_INDEXINFOJS ' "' . $searchExtensions[$contentIndex] . '": ' . ($content->[$contentIndex] ? 'true' : 'false'); + }; + + print FH_INDEXINFOJS "\n }"; + }; + + print FH_INDEXINFOJS + "\n }"; + + close(FH_INDEXINFOJS); + }; + + + +############################################################################### +# Group: Section Functions + + +# +# Function: BuildTitle +# +# Builds and returns the HTML page title of a file. +# +# Parameters: +# +# sourceFile - The source to build the title of. +# +# Returns: +# +# The source file's title in HTML. +# +sub BuildTitle #(sourceFile) + { + my ($self, $sourceFile) = @_; + + # If we have a menu title, the page title is [menu title] - [file title]. Otherwise it is just [file title]. + + my $title = NaturalDocs::Project->DefaultMenuTitleOf($sourceFile); + + my $menuTitle = NaturalDocs::Menu->Title(); + if (defined $menuTitle && $menuTitle ne $title) + { $title .= ' - ' . $menuTitle; }; + + $title = $self->StringToHTML($title); + + return $title; + }; + +# +# Function: BuildMenu +# +# Builds and returns the side menu of a file. +# +# Parameters: +# +# sourceFile - The source to use if you're looking for a source file. +# indexType - The index to use if you're looking for an index. +# +# Both sourceFile and indexType may be undef. +# +# Returns: +# +# The side menu in HTML. +# +# Dependencies: +# +# - and require this section to be surrounded with the exact +# strings "". +# - This function depends on the way formats file and index entries. +# +sub BuildMenu #(FileName sourceFile, TopicType indexType) -> string htmlMenu + { + my ($self, $sourceFile, $indexType) = @_; + + if (!$menuNumbersAndLengthsDone) + { + $menuGroupNumber = 1; + $menuLength = 0; + %menuGroupLengths = ( ); + %menuGroupNumbers = ( ); + $menuRootLength = 0; + }; + + my $outputDirectory; + + if ($sourceFile) + { $outputDirectory = NaturalDocs::File->NoFileName( $self->OutputFileOf($sourceFile) ); } + elsif ($indexType) + { $outputDirectory = NaturalDocs::File->NoFileName( $self->IndexFileOf($indexType) ); } + else + { $outputDirectory = NaturalDocs::Settings->OutputDirectoryOf($self); }; + + + # Comment needed for UpdateFile(). + my $output = '