OODoc/lib/OODoc.pod
=encoding utf8
=head1 NAME
OODoc - object oriented production of software documentation
=head1 INHERITANCE
OODoc
is an OODoc::Object
=head1 SYNOPSIS
use OODoc;
my $doc = OODoc->new(distribution => 'My Name', version => '0.02');
$doc->processFiles(workdir => $dest);
$doc->finalize;
$doc->formatter('pod', workdir => $dest)->createPages;
$doc->formatter('html', workdir => '/tmp/html')->createPages;
or use the C<oodist> script, included in this distribution (advised).
=head1 DESCRIPTION
"OODoc" stands for "Object Oriented Documentation": to create better
manual-pages in HTML and Perl's POD format than produced by the standard
offerings of the Perl tool-chain.
Do not forget to B<read> the L</DETAILS> section (further down on this
manual-page) to get started. Please contribute ideas. Have a look at
the main website of this project at L<https://perl.overmeer.net/oodoc/>.
That is also an example of the produced html output (we are working on
nicer visuals)
Extends L<"DESCRIPTION" in OODoc::Object|OODoc::Object/"DESCRIPTION">.
=head1 OVERLOADED
Extends L<"OVERLOADED" in OODoc::Object|OODoc::Object/"OVERLOADED">.
=over 4
=item overload: B<'!='> (numeric different)
Inherited, see L<OODoc::Object/"OVERLOADED">
=item overload: B<'=='> (numeric equivalent)
Inherited, see L<OODoc::Object/"OVERLOADED">
=item overload: B<'bool'>
Inherited, see L<OODoc::Object/"OVERLOADED">
=back
=head1 METHODS
Extends L<"METHODS" in OODoc::Object|OODoc::Object/"METHODS">.
=head2 Constructors
Extends L<"Constructors" in OODoc::Object|OODoc::Object/"Constructors">.
=over 4
=item $class-E<gt>B<new>(%options)
Create this general manager object. When you use the C<oodist> script,
these parameters are read from the configuration in F<Makefile.PL>
(actually F<MYMETA.json>).
Improves base, see L<OODoc::Object/"Constructors">
-Option --Default
distribution <required>
project $distribution
version <from version or VERSION file>
=over 2
=item distribution => STRING
The name of the package, as released on CPAN.
=item project => STRING
A short description of the C<$distribution>, as will be shown on many places
in the produced manual pages and code. You can use the main package name,
or something which is nicer to read.
=item version => STRING
The version number as automatically included in all packages after
each package statement and on many places in the documentation. By
default the current directory is searched for a file named F<version>
or F<VERSION> which contains a number.
=back
=back
=head2 Attributes
Extends L<"Attributes" in OODoc::Object|OODoc::Object/"Attributes">.
=over 4
=item $obj-E<gt>B<distribution>()
Returns the nice name for the distribution.
=item $obj-E<gt>B<index>()
Returns the L<OODoc::Index|OODoc::Index> which maintains the collected information.
=item $obj-E<gt>B<project>()
Returns the general project description, by default the distribution name.
=item $obj-E<gt>B<publish>(\%options)
Inherited, see L<OODoc::Object/"Attributes">
=item $obj-E<gt>B<unique>()
Inherited, see L<OODoc::Object/"Attributes">
=item $obj-E<gt>B<version>()
Returns the version string for the distribution.
=back
=head2 Parser
=over 4
=item $obj-E<gt>B<processFiles>(%options)
Extract the documentation from the selected files.
-Option --Default
distribution <from main OODoc object>
manifest "$source/MANIFEST"
notice ''
parser OODoc::Parser::Markov
select qr/\.(pod|pm)$/
skip_links []
source '.'
version <from source directory or OODoc object>
workdir undef
=over 2
=item distribution => NAME
Useful when more than one distribution is merged into one set of
documentation.
=item manifest => $file
The MANIFEST C<$file> lists all files which belong to this distribution: packages,
pods, tests, etc. before the new pod files are created.
=item notice => $text
Include the C<$text> (which may consist of multiple lines) to each of the
pm files. This notice usually contains the copyright message.
=item parser => CLASS|$name|$parser
The parser C<CLASS> or C<$parser> object to be used to process the pages.
=item select => ARRAY|REGEX|CODE
The files which contain documentation to be processed. You can provide
a list of filenames as array reference, a C<REGEX> which is used to select
names from the MANIFEST file, or a C<CODE> reference which is used to
select elements from the MANIFEST (filename passed as first argument).
Is your pod real pod or should it also be passed through the parser?
=item skip_links => ARRAY|STRING|REGEXP
Passed to L<OODoc::Parser::new(skip_links)|OODoc::Parser/"Constructors">.
=item source => $directory
The location where the files are located. This is useful when you collect
the documentation of other distributions into the main one. Usually in
combination with an undefined value for C<workdir>.
=item version => STRING
The version of the distribution. If not specified, the C<source>
directory is scanned for a file named F<version> or F<VERSION>. The
content is used as version value. If these do not exist, then the
main OODoc object needs to provide the version.
To make F<Makefile.PL> option C<VERSION_FROM> to work with this
seperate version file, that line should contain something like
our $VERSION = 3.14;
=item workdir => $directory
Specify the C<$directory> where the stripped pm-files and the pod files
will be written to. Probably the whole distribution is collected on
that spot.
When the processed files are not part of this distribution, then
then do not specify this option: knowledge is built, but not
included in the release.
=back
=item $obj-E<gt>B<selectFiles>($filter, @files)
Split the C<@files> into two sets: the first with C<@files> to process, and the second
with C<@files> which do not need to be processed. The selecting C<$filter> comes from
L<processFiles(select)|OODoc/"Parser"> and the C<@files> are originally read from a F<MANIFEST>.
Returned are two ARRAY (references).
=back
=head2 Actions
=over 4
=item $obj-E<gt>B<finalize>(%options)
[3.01] After all documentation fragments have been read via L<processFiles()|OODoc/"Parser">,
the pages need to be composed together. For instance, inheritance and final
cleanups are due here.
=item $obj-E<gt>B<formatter>($name|$class|$object, %options)
[2.03] Create a manual for the set of manuals read so far. The manuals are
produced by different formatters which produce one page at a time.
Returned is the formatter which is used: it may contain useful information
for you.
The first, optional argument specifies the type of pages to be produced.
This can be either a predefined C<$name> (currently available are C<pod>
and C<html>, representing L<OODoc::Format::Pod|OODoc::Format::Pod> and L<OODoc::Format::Html|OODoc::Format::Html>
respectively), the name of a C<$class> which needs to be instantiated,
or an instantiated formatter C<$object>.
You can also pass many options which are passed to (the effective extension
of) L<OODoc::Format::createPages()|OODoc::Format/"Page generation">.
-Option --Default
manifest workdir/MANIFEST
workdir <required>
=over 2
=item manifest => FILENAME|undef
The names of the produced files are appended to this file content. When C<undef>
is given, no file will be written for this.
=item workdir => $directory
The C<$directory> where the output is going to.
=back
=item $obj-E<gt>B<getPackageRelations>()
Compile all files which contain packages, and then try to find-out
how they are related.
=item $any-E<gt>B<mkdirhier>($directory)
Creates this C<$directory> and all its non-existing parents.
=item $obj-E<gt>B<stats>()
Returns a string which contains some statistics about the whole parsed
document set.
=back
=head1 DETAILS
=head2 OODoc
The "OO" part of the name refers to two things: this module simplifies
writing documentation for Object Oriented programs. At the same time,
it is Object Oriented itself: easily extensible. It can be used to
integrate manual-pages from many distributions into one homogeneous set.
OODoc has been used for small single package upto very large sets of
modules, like the MailBox suite.
=head3 Adding logical markup
POD (Perl's standard Plain Old Document format) has a very simple
syntax. POD is very simple to learn, and the produced manual pages
look like standard Unix manual pages. However, when you start writing
larger programs, you start seeing the weaker aspects of POD.
One of the main problems with POD is that is using a visual markup style:
you specify information by how it must be presented to the viewer.
This in contrast with logical markup where you specify the information
more abstract, and a visual representation is created by an application.
For instance, HTML defines an C<< <I> >> tag as visual markup Italic,
and C<< <EM> >> as logical markup for EMphasis, which will usually show
in italic.
The main disadvantage of visual markup is limited expression: the
formatter of the manual page can not help the author of the documentation
to produce more consistent and complete manual pages. This is not a
problem for small distributions, but is much more needed when code
grows larger.
=head3 Application
This module can be used directly, but you may also use the C<oodist>
script which comes with this distribution. That command will also help
you with your whole distribution release process.
The documentation syntax can be changed by configuring the provided
parser or adding a new one. The L<OODoc::Parser::Markov|OODoc::Parser::Markov> parser
extends standard POD, which uses visual markup, with logical markup tags.
The output is produced by formatters and exporters. The current
implementation contains three POD formatters, one HTML formatter,
and a JSON exporter.
=head2 How OODoc works
Like with POD, you simply mix your documentation with your code. When
the module is distributed, this information is stripped from the files
by a I<parser>, and translated into an object tree. This tree is then
optimized: items combined, reorganized, etc, to collect all information
required to produce useable manual pages.
Then, a I<formatter> is called to generate the manual pages in real
POD or HTML. You may also use an I<exporter> to serialize that tree
(into JSON).
My-Dist -------+ +--formatter--> POD
My-Other-Dist -|--parser--> DocTree --|--formatter--> HTML
Even-More -----+ +--exporter---> JSON/HTML
=head3 The parser
The parser reads the package files, and (by default) strips them from
all documentation fragments. The stripped C<pm> files are written to
a temporary directory which is used to create the distribution release.
Existing C<pod> files will also be consumed, but published untouched.
The parser produces an object tree, which is a structured representation
of the documentation. That tree is parser independent, and organized
by manual page.
It is possible to use more than one parser for your documentation. On
this moment, there is only one parser implemented: the "Markov parser",
named after the author. You can add your own parser, if you prefer to.
Within one distribution, different files may be parsed by different parsers.
=head3 collecting relations
The second phase of the manual page generation process figures out the
relations between the manual pages. It collects inheritance relations
and other organizational information, which is to be used by the
manual page generators.
Links are being checked. The Markov parser let you refer to subroutines
and even documented options within a sub.
Information of super-classes is merged: sections, methods, method options
and their defaults. Methods are sorted by name per ((sub)sub)section.
=head3 formatter
The final phase can be called more than once: based on the same object
tree, documents can be produced in various formats. The current
implementations produce POD and HTML.
More details in the L<OODoc::Format|OODoc::Format> base-class.
=head3 exporters
You may also export the documentation tree to be used with your own
separate application. At this moment, that dump will be made in JSON
with HTML-formatted text fragments only.
More details in the L<OODoc::Export|OODoc::Export> base-class.
=head2 Release process
OODoc, as document generator, will need to be integrated into your
software release process.
=head3 do it yourself
To use OODoc, you need a script which helps you producing
the distribution of your module. The simpest script looks like this:
use OODoc;
my $dist = '/tmp/abc';
my $doc = OODoc->new(
distribution => 'E-mail handling',
version => '0.01',
);
$doc->processFiles(...); # parsing
$doc->finalize(...); # collecting
$doc->formatter('pod', ...)->createPages(...);
# formatting to POD
The default parser will be used to process the files, see
L<OODoc::Parser::Markov|OODoc::Parser::Markov> for its syntax. The formatter is described
in L<OODoc::Format::Pod|OODoc::Format::Pod>. Once you have this working, you may decide
to add options to the calls to adapt the result more to your own taste.
=head3 use oodist
This distribution comes with a script named C<oodist>, which automates
most steps of your release process (to CPAN). To start using OODoc with
your existing distribution, simply run this:
=over 4
=item 1. go to the root directory of your module
=item 2. run 'oodist'
=item 3. follow the instructions to configure oodist
=item 4. run 'oodist -v'
=back
This should take you more than a few minutes. When the output looks fine,
then start playing with the advantages of the Markov extended POD syntax.
=head3 Checking the produced manual pages
To test the document production for C<My::Module>, try (on UNIX/Linux)
pod2man $dist/lib/My/Module.pod | man -l -
=head1 DIAGNOSTICS
=over 4
=item Info: * collect package relations
Cast by finalize()
=item Info: * create inheritance chapters
Cast by finalize()
=item Info: * expand manual contents
Cast by finalize()
=item Info: * finalize each manual
Cast by finalize()
=item Error: cannot compile $pkg class: $err
The C<$pkg> parser class does not exist or produces compiler errors.
Cast by processFiles()
=item Fault: cannot copy distribution file $from to $to: $!
For some reason, a plain file can not be copied C<$from> your source
tree C<$to> the location where the distribution is made.
Cast by processFiles()
=item Fault: cannot create $dir: $!
Cast by mkdirhier()
=item Fault: cannot read distribution version from file $file: $!
Cast by new()
=item Fault: cannot read version from $file: $!
A C<$file> named F<version> or F<VERSION> was found to contain the
distribution version, but not accessible.
Cast by processFiles()
=item Info: compiling all packages
Cast by getPackageRelations()
=item Info: detect inheritance relationships
Cast by getPackageRelations()
=item Warning: errors from $manual: $err
Syntax error in your code, or a problem caused by stripping the file.
You can run your test-scripts before the files get stripped as long
as you do not use C<make test>, because that will try to produce
manual-pages as well...
Cast by getPackageRelations()
=item Error: formatter() requires a directory to write the manuals to
You have to provide a value to C<workdir>, which will be used as top directory
for the produced output. It does not matter whether there is already some
stuff in that directory.
Cast by formatter()
=item Warning: no file $file to include in the distribution
Probably your MANIFEST file lists this C<$file> which does not exist.
The C<$file> will be skipped for now, but may cause problems later on.
Cast by processFiles()
=item Error: no version specified for distribution $dist
Version information will be added to all packages and all manual
pages. You need to specify a version and be sure that it changes
with each release, or create a file named F<version> or F<VERSION>
which contains that data.
Cast by new()
=item Error: parser $name could not be instantiated
Something went wrong while starting the parser object. Probably there is
an other error message which will tell you the exact cause.
Cast by processFiles()
=item Error: requires a directory to write the distribution to
You have to give a value to C<workdir>, which may be C<undef>. This
option is enforced to avoid the accidental omission of the parameter.
When processing the manifest file, some files must be copied directly
to a temporary directory. The packages are first stripped from
their pseudo doc, and then written to the same directory. That
directory will be the place where C<< make dist >> is run later.
Cast by processFiles()
=item Error: the produced distribution needs a project description
Cast by new()
=item Error: there is no version defined for the source files
Each manual will need a version number. There are various ways to
specify one. For instance, create a file named F<version> or F<VERSION>
in the top source directory of your distribution, or specify a version
as argument to L<OODoc::new()|OODoc/"METHODS"> or L<OODoc::processFiles()|OODoc/"Parser">.
Cast by processFiles()
=item Error: use regex, code reference or array for file selection, not $type
The L<processFiles(select)|OODoc/"Parser"> option is not understood. You may specify
an ARRAY, regular expression, or a CODE reference.
Cast by selectFiles()
=back
=head1 SEE ALSO
This module is part of OODoc version 3.04,
built on September 12, 2025. Website: F<https://perl.overmeer.net/oodoc/>
=head1 LICENSE
For contributors see file ChangeLog.
This software is copyright (c) 2003-2025 by Mark Overmeer.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.