NAME
App::FuguWeb::Config - the site description over Fugu::Config
SYNOPSIS
use App::FuguWeb::Config;
my $config = App::FuguWeb::Config->load(error => \my $reason)
or die "$reason\n";
say $config->site;
say $_->{href} for $config->nav;
say $_->{file} for $config->pages;
DESCRIPTION
The class reads .fuguwebrc, applies the defaults, and validates the result. The grammar, the quoting, and the yes/no spellings come from Fugu::Config; this class holds what is true of a site.
The object is immutable once loaded, and the module keeps no package state. Two sites in one process therefore share nothing.
METHODS
load
App::FuguWeb::Config->load(
root => $dir, # default: discover
error => \my $reason,
)
Read and validate the description. The method returns the object, or undef with the reason in $reason.
Without root, the method walks up from the working directory to the first directory that holds .fuguwebrc, as fuguvm finds .fuguvmrc.
The reason travels through a reference because the object that would hold it does not exist when the load fails.
A load fails when the file is absent, when a line does not parse, or when the description would make the build do something it must not. Every message names the file, and the block when a block is at fault.
The description is rejected when:
there is no
sitesetting;a
pageblock names no source, or more than one;two
pageblocks name the same file, or two manuals would become the same page;a
navblock has no label;a path setting steps out of the project with a
..component;a
pageblock name is absolute or steps out of the output directory: the name becomes a file there, so it is a path and gets the same guard the sources get;a
manualsnamespace holds a path separator: it prefixes a manual name, and that name becomes both the staged file and the published page;a
modulesdirectory is not belowmodule_root, which would leave the module with no name to take but its whole path;a yes/no setting holds something that is neither;
the source directory holds a symlink. Every file there that the build does not render is copied into the site, so a symlink would publish whatever it points at, from anywhere on the machine.
root, path
The project root, and the .fuguwebrc that this object read.
source_path
my $dir = $config->source_path;
my $file = $config->source_path('footer.body.html');
The source directory, or one file in it.
site, lang, out_dir, source_dir, entry, module_root, mandoc_os, man_url, stylesheet
The settings. site is the only one a project must give.
site (required) the name in the title of every page,
and the text of the header link
lang en the lang attribute of the document
out_dir web/build where the build writes
source_dir web the fragments and the assets
entry index.html the front page, and the header link
module_root lib the prefix a module name drops
(a trailing slash is dropped)
mandoc_os OpenBSD the mandoc -I os=, which pins the footer
man_url https://man.openbsd.org/ where a remote .Xr goes
stylesheet (searched) the base stylesheet
stylesheet overrides the search that "share_path" in Fugu::File does. The search finds the sheet in a checkout and in an installed App-FuguWeb distribution alike, so most projects never set it.
The pod2man --center and --release values are not settings. They are constants of App::FuguWeb::Render: they pin the pod2man output so the site does not vary with the build host.
nav
The navigation, in file order. Each entry is a hashref with href and label.
pages
The pages, in file order. Each entry is a hashref:
file the name of the page in the output
title the title, which defaults to the file name
source one of body, markdown or index
value what the source names, and undef for index
unlinked true when no other page links to it
groups
The manual groups, in file order. Each entry is an App::FuguWeb::Config::Group, and the two block types interleave as the description wrote them.
inventory
Every name that the output directory must hold after a build: the pages of the description, one page for each manual of each group, the stylesheet, and the assets. The build and the checks read the same list, so the two can never disagree about what the site holds.
GROUPS
A manuals or modules block becomes one group. A group never holds a list of manuals: it reads its directory, so a manual that is added reaches the site with no edit anywhere.
A group whose directory does not exist fails the load and names the directory. A silent empty group hides a typo in a path, and a rename that nothing catches is what this file exists to prevent.
kind, heading, anchor, namespace
kind is manuals or modules. heading is the block name, which becomes the <h2>, and anchor its id.
manuals
The manuals of the group, in the order the index shows them, as App::FuguWeb::Manual objects. The method reads the directory once and keeps the answer.
A manuals group reads its directory for *.1, *.3p, *.5 and *.8, and takes a plain file only. It does not glob: Perl's glob splits its pattern on whitespace and reads [ ] { } ? ~, so a project whose path holds one of them would lose its manuals or collect a sibling directory's. It sorts by section, in the order 1, 3p, 5, 8, and then by file name. The namespace setting prefixes the name and the staged file name, so man/fugu/Daemon.3p becomes Fugu::Daemon(3p).
A modules group finds every .pod file below its directory, and the sidecar that names the directory itself: lib/App/FuguWeb.pod is the umbrella of lib/App/FuguWeb/. It sorts by path, so Store.pod stays before Store/Memory.pod.
Both sorts compare bytes and never read the locale of the builder. A site must not depend on the machine that built it.
Never name a directory that holds more than one namespace. In this repository lib/App is such a directory, and one group there would swallow three namespaces.
SEE ALSO
App::FuguWeb, App::FuguWeb::Manual, Fugu::Config, fuguweb(1)
AUTHOR
Dick Olsson <hi@senzilla.io>