NAME

App::FuguWeb::Render - the three external renderers

SYNOPSIS

use App::FuguWeb::Render;

my $render = App::FuguWeb::Render->new(config => $config);

my $missing = $render->probe;       # a tool that is not installed
$render->lint(@mdoc_sources)        or die "a manual is malformed\n";

my $html = $render->markdown('INSTALL.md');
my $man  = $render->mdoc('Fugu::Daemon.3p', "$out/.man");
my $pod  = $render->pod($path, 'Fugu::Daemon', '2026-08-04');

DESCRIPTION

The tool renders no format itself. mandoc turns mdoc(7) into HTML, lowdown turns Markdown into HTML, and pod2man turns POD into mdoc for mandoc to finish. Each one is a mature program that reads a format this project already writes; a Perl reimplementation would be a second, worse one.

Every method returns the output as bytes, or undef with a message in the log.

METHODS

new

App::FuguWeb::Render->new(
    config  => $config,     # required
    log     => $logger,     # default: Fugu::Log->default
    mandoc  => $program,    # default: mandoc
    lowdown => $program,    # default: lowdown
    pod2man => $program,    # default: pod2man
)

The tool names are overridable, so a caller can name another binary and a test can name one that is not there.

probe

The name of the first renderer that is not on the path, or undef when all three are there. The caller reports the name and exits with EXIT_TOOL_MISSING, so an operator learns which package to install and not that "the build failed".

lint

$render->lint(@paths)

Run mandoc -Tlint -W warning over every mdoc source. The method returns true when every page is clean, and undef with the diagnostics in the log otherwise. A malformed page must fail the build, not render badly.

markdown

$render->markdown($path)

Render one Markdown file into an HTML body fragment, with lowdown -Thtml.

mdoc

$render->mdoc($file, $dir)

Render one staged mdoc source into an HTML body fragment. The child runs in $dir, through the cwd option of "run" in Fugu::Process.

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. That is why App::FuguWeb::Site stages every source in one directory under its "staged_name" in App::FuguWeb::Manual, and why the child has to start there.

pod

$render->pod($path, $name, $date)

Render one POD sidecar into an HTML body fragment. pod2man writes mdoc, and mandoc finishes the job, so a module page carries the same chrome as a hand-written manual.

$date comes from the caller and never from the file time: git does not preserve file times, so a build that read one would give different bytes on every checkout. "pod_date" in App::FuguWeb::Site supplies it.

pod2man reports a malformed directive on standard error and still writes the page. The page is what the site needs, so a diagnostic is a warning and only empty output is fatal.

Note that pod2man renders Some::Module as italic text, not as a link. POD pages therefore cross-reference as plain text while mdoc pages link. Making it work would mean post-processing the HTML of mandoc.

The --center and --release values are the POD_CENTER and POD_RELEASE constants. They are constants and not settings: they pin the pod2man output so the site does not vary with the build host. Without them, pod2man writes its own center text and the perl version of the machine that built the site.

html_options

The mandoc options that every page shares.

-I os= pins the footer, which otherwise names the operating system of the build host, and the site would then vary with the machine that built it.

The ./ in the man= template matters. A module page is named Fugu::Daemon.3p.html, and a browser reads a relative URL whose first segment holds a colon as a scheme.

SEE ALSO

App::FuguWeb, App::FuguWeb::Site, Fugu::Process, mandoc(1), lowdown(1), pod2man

AUTHOR

Dick Olsson <hi@senzilla.io>