NAME
App::FuguWeb::Site - the whole build, from the description to the pages
SYNOPSIS
use App::FuguWeb::Site;
my $site = App::FuguWeb::Site->new(
config => $config,
out => 'web/build',
);
unless ($site->build) {
my $missing = $site->missing_tool;
die "$missing not found\n" if defined $missing;
die "the build failed\n";
}
$site->clean;
DESCRIPTION
One method renders the site. Each step reports its own failure and stops the build: a site that is half rendered must not look like a success.
The build reads nothing from the network, writes nothing outside the output directory, and gives the same bytes for the same checkout.
METHODS
new
App::FuguWeb::Site->new(
config => $config, # required
out => $dir, # required: the output directory
log => $logger, # default: Fugu::Log->default
render => $render, # default: one over the same description
)
config, staging
The site description, and the mdoc staging directory.
missing_tool
The renderer that failed the probe of the last "build", or undef. The build probes once and names the tool in the log; the caller maps this value to its own exit code, so an operator learns which package to install.
build
Render the whole site:
check that every renderer is installed, and name the first one that is not;
refuse an output directory that no build may own;
lint every mdoc source;
create the output directory and the staging directory inside it;
copy every mdoc source into the staging directory under its staged name;
copy the base stylesheet and every asset;
render each
pageblock;render one page for each manual in each group;
remove the staging directory, and every file the site no longer holds.
The last step is what makes a second build over the same directory right. A manual that was renamed leaves its old page behind, and a site that carried both would fail its own check. The build owns the output directory, so it owns the removal too; it removes a plain file and never a tree.
The method returns true on success, and undef with a message in the log otherwise.
The output directory is created on purpose. The recipe that this replaced got it as a side effect of the staging mkdir, which would have broken the moment the staging step moved.
clean
Remove the output directory. The method returns true when the directory is gone, whether or not it was there to begin with.
clean removes a built site and refuses anything else. It deletes a tree without asking, so the one thing it must never do is delete a tree that no build made. A build writes one flat directory of files, plus the staging directory while it runs; a target that holds anything else is refused by name.
THE OUTPUT DIRECTORY
Both build and clean refuse a target that no build may own: the root of the filesystem, the home directory, the project root, and any directory that holds the project. --out reaches them both, and the out_dir setting it overrides is checked in the description, so the guard has to sit here as well.
The rule is deliberately not "inside the project". The tests and the CI both build into a temporary directory outside it.
A .. in the target is resolved before the comparison. File::Spec->canonpath leaves it alone by design, and a guard that compared the uncollapsed form would let <project>/.. through as a directory it had never seen.
pod_date
The date that every POD page carries: the date of the last commit, and today when git does not answer. git does not preserve file times, so a build that read one would give different bytes on every checkout.
THE STAGING DIRECTORY
mandoc decides between a local link and a link to the manual host by looking for a file named %N.%S in its working directory. Every mdoc source is therefore copied into one directory under its "staged_name" in App::FuguWeb::Manual, and mandoc runs there.
The directory lives inside the output directory, under .man, and the build removes it. Staging is a build detail: a published tree that carried it would serve the mdoc sources beside the pages made from them.
ASSETS
An asset is any file directly in the source directory that the build does not render: not a *.body.html fragment, not Markdown, and not a dot file. robots.txt and CNAME therefore need no entry in the description, and a CLAUDE.md beside them is not published.
Markdown in the source directory is either a page source, which a page block names and lowdown renders, or notes for the maintainers. Neither belongs in the output as it stands.
THE STYLESHEET
The base stylesheet ships with the tool, at share/fuguweb/style.css, and "share_path" in Fugu::File finds it: in a checkout through this module's location, and under the share tree of an installed App-FuguWeb distribution. The stylesheet setting overrides the search.
A stylesheet that is not found fails the build and names the path. A site with no stylesheet must not look like a success.
SEE ALSO
App::FuguWeb, App::FuguWeb::Config, App::FuguWeb::Render, App::FuguWeb::Page, App::FuguWeb::Index, Fugu::File
AUTHOR
Dick Olsson <hi@senzilla.io>