App-FuguWeb
view release on metacpan or search on metacpan
lib/App/FuguWeb.pod view on Meta::CPAN
=head1 NAME
App::FuguWeb - a static documentation site for a Perl project
=head1 SYNOPSIS
fuguweb build --out web/build
fuguweb check --out web/build
use App::FuguWeb;
my $safe = App::FuguWeb::escape_html($title);
my $file = App::FuguWeb::CONFIG_FILE; # .fuguwebrc
=head1 DESCRIPTION
C<fuguweb> renders one static site from the documentation that a Perl
project already keeps: mdoc(7) manuals, POD sidecars, and Markdown.
There is no templating language and no JavaScript. The tool runs
C<mandoc>, C<lowdown>, and C<pod2man>, and wraps each result in one
shared chrome.
A project needs no build recipe. It writes one F<.fuguwebrc> at its
root, keeps its body fragments and its assets in one source directory,
and runs C<fuguweb build>. See L<fuguweb(1)> for the subcommands and
the exit codes.
This file holds what more than one module in the namespace needs: two
constants and four functions, documented below. The rest of the work
is split by concern:
=over 4
=item L<App::FuguWeb::Config>
The site description: the settings, the navigation, the pages, and the
manual groups.
=item L<App::FuguWeb::Page>
The chrome around one body fragment.
=item L<App::FuguWeb::Render>
The three external renderers.
=item L<App::FuguWeb::Manual>
One manual source: its path, name, section, page, and description.
=item L<App::FuguWeb::Index>
The body of the manual index.
=item L<App::FuguWeb::Site>
The whole build.
=item L<App::FuguWeb::Check>
The checks over a built site.
=item L<App::FuguWeb::CLI>
Subcommand dispatch over L<Fugu::CLI>.
=back
=head1 THE CONFIGURATION FILE
F<.fuguwebrc> sits at the project root and uses the L<Fugu::Config>
grammar: a setting on a line of its own, and a block that opens with a
brace at the end of its header line. A C<#> starts a comment, and the
grammar has no escape for it, so a value may not hold one.
site = OpenHAP
out_dir = web/build
source_dir = web
entry = index.html
nav "fugu.html" {
label = Fugu
}
page "install.html" {
title = Install
markdown = INSTALL.md
}
manuals "Fugu" {
dir = man/fugu
anchor = fugu
namespace = "Fugu::"
}
modules "OpenHAP modules" {
dir = lib/App/OpenHAP
anchor = modules
}
A C<page> block names exactly one source: C<body> for a fragment in the
source directory, C<markdown> for a Markdown file, or C<index = yes>
for the generated manual index. C<unlinked = yes> marks a page that no
other page links to, such as F<404.html>.
Three rules keep a list out of the file. A C<manuals> block reads its
directory. A C<modules> block finds every F<.pod> file below its
directory, and the sidecar that names the directory itself. Every file
in the source directory that the build does not render is an asset, and
the build copies it; L<App::FuguWeb::Site/ASSETS> says exactly which
those are.
A C<keys> block and its C<key> blocks describe the published key
directory of an organization. L<App::FuguWeb::Keys> documents them.
L<App::FuguWeb::Config> documents every setting and every default.
=head1 FUNCTIONS
=head2 escape_html
my $safe = App::FuguWeb::escape_html($text);
Escape C<&>, C<< < >> and C<< > >>, in that order. The function takes
bytes and returns bytes: no file in the namespace carries C<use utf8>,
so a multi-byte character passes through untouched.
=head2 escape_attr
my $safe = App::FuguWeb::escape_attr($text);
The same, plus the double quote. Use it for a value on its way into a
double-quoted attribute: a value that holds a quote ends the attribute
early, and everything after it becomes markup. L</escape_html> alone
does not guard an attribute.
=head2 list_dir
my $names = App::FuguWeb::list_dir($dir) or die "cannot read: $!";
The names in one directory, sorted, without C<.> and C<..>. The
function returns an array reference, or C<undef> with the reason in
C<$!>, so a caller can tell an empty directory from one it cannot
read.
The sort compares bytes and never reads the locale of the builder: a
site must not depend on the machine that built it.
=head2 list_tree
my $paths = App::FuguWeb::list_tree($dir) or die "cannot read: $!";
Every leaf below the directory, as paths relative to it: each file,
each symlink, and each directory that holds nothing. The function
returns an array reference, or C<undef> with the reason in C<$!>.
The function recurses into a plain directory, and never through a
symlink. A symlinked directory is one entry: the build owns neither the
target of the link nor what sits under it.
An empty directory is a leaf, so a caller sees it. A walk that answered
( run in 1.278 second using v1.01-cache-2.11-cpan-364913b4093 )