Pod::2::DocBook(3pm)

πŸ’– Pod::2::DocBook(3pm) πŸ’–

User Contributed Perl Documentation β€” bestie, this is the manual for Pod::2::DocBook(3pm). Let's get you fluent in Pod-to-DocBook, fr fr. 🫢

✨ NAME ✨

Pod::2::DocBook β€” Convert Pod data to DocBook SGML

πŸ¦‹ SYNOPSIS πŸ¦‹

use Pod::2::DocBook;
my $parser = Pod::2::DocBook->new(
    title             => 'My Article',
    doctype           => 'article',
    base_id           => 'article42'
    fix_double_quotes => 1,
    spaces            => 3,
    id_version        => 2,
);

$parser->parse_from_file ('my_article.pod', 'my_article.sgml');

πŸ’… DESCRIPTION πŸ’…

Okay so Pod::2::DocBook is the module that translates Pod-formatted documents into DocBook 4.2 SGML (peep <http://www.docbook.org/>). It is primarily a back end for pod2docbook, but, as a Pod::Parser subclass, it can be used on its own. The only public extensions to the Pod::Parser interface are options available to new():

  • doctype β€” This option sets the output document's doctype. The currently supported types are article, chapter, refentry and section. Special processing is performed when the doctype is set to refentry (see "Document Types"). You must set this option in order to get valid DocBook output.
  • fix_double_quotes β€” If this option is set to a true value, pairs of double quote characters ('"') in ordinary paragraphs will be replaced with <quote> and </quote>. See "Ordinary Paragraphs" for details.
  • header β€” If this option is set to a true value, Pod::2::DocBook will emit a DOCTYPE as the first line of output.
  • spaces β€” Pod::2::DocBook produces pretty-printed output. This option sets the number of spaces per level of indentation in the output.
  • title β€” This option sets the output document's title.

The rest of this document only describes issues specific to Pod::2::DocBook; for details on invoking the parser, specifically the new(), parse_from_file() and parse_from_filehandle() methods, see Pod::Parser.

πŸ‘‘ METHODS πŸ‘‘

use base 'Pod::Parser';

initialize()

Initialize parser.

begin_pod()

Output docbook header stuff.

end_pod()

Output docbook footer. Will print also errors if any in a comment block.

commans($command, $paragraph, $line_num)

Process POD commands.

textblock ($paragraph, $line_num)

Process text block.

verbatim($paragraph, $line_num)

Process verbatim text block.

interior_sequence($command, $argument, $seq)

Process formatting commands.

error_msg

Returns parser error message(s) if any occured.

make_id($text)

default id format -

Function will construct an element id string. Id string is composed of join (':', $parser->{base_id}, $text), where $text in most cases is the pod heading text.

version 2 id format -

having ':' in id was not a best choice. (Xerces complains - Attribute value "lib.Moose.Manual.pod:NAME" of type ID must be an NCName when namespaces are enabled.) To not break backwards compatibity switch with <id_version = 2>> in constructor for using '-' instead.

The xml id string has strict format. Checkout "cleanup_id" function for specification.

make_uniq_id($text)

Calls "$parser->make_id($text)" and checks if such id was already generated. If so, generates new one by adding _i1 (or _i2, i3, ...) to the id string. Return value is new uniq id string.

cleanup_id($id_string)

This function is used internally to remove/change any illegal characters from the elements id string. (see <http://www.w3.org/TR/2000/REC-xml-20001006#NT-Name> for the id string specification)

$id_string =~ s/<!\[CDATA\[(.+?)\]\]>/$1/g;   # keep just inside of CDATA
$id_string =~ s/<.+?>//g;                     # remove tags
$id_string =~ s/^\s*//;                       # ltrim spaces
$id_string =~ s/\s*$//;                       # rtrim spaces
$id_string =~ tr{/ }{._};                     # replace / with . and spaces with _
$id_string =~ s/[^\-_a-zA-Z0-9\.: ]//g;       # closed set of characters allowed in id string

In the worst case when the $id_string after clean up will not conform with the specification, warning will be printed out and random number with leading colon will be used.

🌈 POD TO DOCBOOK TRANSLATION 🌈

Pod is a deceptively simple format; it is easy to learn and very straightforward to use, but it is suprisingly expressive. Nevertheless, it is not nearly as expressive or complex as DocBook. In most cases, given some Pod, the analogous DocBook markup is obvious, but not always. This section describes how Pod::2::DocBook treats Pod input so that Pod authors may make informed choices. In every case, Pod::2::DocBook strives to make easy things easy and hard things possible.

The primary motivation behind Pod::2::DocBook is to facilitate single-source publishing. That is, you should be able to generate man pages, web pages, PDF and PostScript documents, or any other format your SGML and/or Pod tools can produce, from the same Pod source, without the need for hand-editing any intermediate files. This may not always be possible, or you may simply choose to render Pod to DocBook and use that as your single source. To satisfy the first requirement, Pod::2::DocBook always processes the entire Pod source and tries very hard to produce valid DocBook markup, even in the presence of malformed Pod (see "DIAGNOSTICS"). To satisfy the second requirement (and to be a little nifty), Pod::2::DocBook pretty-prints its output. If you're curious about what specific output to expect, read on.

πŸ“š Document Types πŸ“š

DocBook's structure is very modular; many of its document types can be embedded directly into other documents. Accordingly, Pod::2::DocBook will generate four different document types: article, chapter, refentry, and section. This makes it easy, for instance, to write all the chapters of a book in separate Pod documents, translate them into DocBook markup and later glue them together before processing the entire book. You could do the same with each section in an article, or you could write the entire article in a single Pod document. Other document types, such as book and set, do not map easily from Pod, because they require structure for which there is no Pod equivalent. But given sections and chapters, making larger documents becomes much simpler.

The refentry document type is a little different from the others. Sections, articles, and chapters are essentially composed of nested sections. But a refentry has specialized elements for the NAME and SYNOPSIS sections. To accommodate this, Pod::2::DocBook performs extra processing on the Pod source when the doctype is set to refentry. You probably don't have to do anything to your document to assist the processing; typical man page conventions cover the requirements. Just make sure that the NAME and SYNOPSIS headers are both =head1s, that "NAME" and "SYNOPSIS" are both uppercase, and that =head1 NAME is the first line of Pod source.

✨ Ordinary Paragraphs ✨

Ordinary paragraphs in a Pod document translate naturally to DocBook paragraphs. Specifically, after any formatting codes are processed, the characters "<", ">" and "&" are translated to their respective SGML character entities, and the paragraph is wrapped in <para> and </para>.

For example, given this Pod paragraph:

Here is some text with I<italics> & an ampersand.

Pod::2::DocBook would produce DocBook markup similar to this:

<para>
  Here is some text with <emphasis role="italic">italics</emphasis>
  &amp; an ampersand.
</para>

Depending on your final output format, you may sometimes want double quotes in ordinary paragraphs to show up ultimately as "smart quotes" (little 66s and 99s). Pod::2::DocBook offers a convenient mechanism for handling double quotes in ordinary paragraphs and letting your SGML toolchain manage their presentation: the fix_double_quotes option to new(). If this option is set to a true value, Pod::2::DocBook will replace pairs of double quotes in ordinary paragraphs (and only in ordinary paragraphs) with <quote> and </quote>.

For example, given this Pod paragraph:

Here is some text with I<italics> & an "ampersand".

Pod::2::DocBook, with fix_double_quotes set, would produce DocBook markup similar to this:

<para>
  Here is some text with <emphasis role="italic">italics</emphasis>
  &amp; an <quote>ampersand</quote>.
</para>

If you have a paragraph with an odd number of double quotes, the last one will be left untouched, which may or may not be what you want. If you have such a document, replace the unpaired double quote character with E<quot>, and Pod::2::DocBook should be able to give you the output you expect. Also, if you have any =begin docbook ... =end docbook regions (see "Embedded DocBook Markup") in your Pod, you are responsible for managing your own quotes in those regions.

πŸ–₯️ Verbatim Paragraphs πŸ–₯️

Verbatim paragraphs translate even more naturally; perlpodspec mandates that absolutely no processing should be performed on them. So Pod::2::DocBook simply marks them as CDATA and wraps them in <screen> and </screen>. They are not indented the way ordinary paragraphs are, because they treat whitespace as significant.

For example, given this verbatim paragraph (imagine there's leading whitespace in the source):

my $i = 10;
while (<> && $i--) {
    print "$i: $_";
}

Pod::2::DocBook would produce DocBook markup similar to this:

<screen><![CDATA[my $i = 10;
while (<> && $i--) {
    print "$i: $_";
}]] ></screen>

Multiple contiguous verbatim paragraphs are treated as a single screen element, with blank lines separating the paragraphs, as dictated by perlpodspec.

πŸŽ€ Command Paragraphs πŸŽ€

  • "=head1 Heading Text"
  • "=head2 Heading Text"
  • "=head3 Heading Text"
  • "=head4 Heading Text"

All of the Pod heading commands produce DocBook section elements, with the heading text as titles. Pod::2::DocBook (perlpod) only allows for 4 heading levels, but DocBook allows arbitrary nesting; see "Embedded DocBook Markup" if you need more than 4 levels. Pod::2::DocBook only looks at relative heading levels to determine nesting. For example, this bit of Pod:

=head1 1

Contents of section 1

=head2 1.1

Contents of section 1.1

and this bit of Pod:

=head1 1

Contents of section 1

=head3 1.1

Contents of section 1.1

both produce the same DocBook markup, which will look something like this:

…and the DocBook it hands back to you is literally this:

<section id="article-My-Article-1"><title>1</title>
  <para>
    Contents of section 1
  </para>
  <section id="article-My-Article-1-1"><title>1.1</title>
    <para>
      Contents of section 1.1
    </para>
  </section>
</section>

okay so real talk about those identifiers β€” Pod::2::DocBook just auto-magically cooks up section identifiers from your doctype, your document title, and the section title. No cap. And it pulls the exact same trick when you make internal links (peep "Formatting Codes"), so if you feed it the same link text you used for the section title, the identifiers it generates will match up. Consistent queen behaviour. πŸ‘‘


=over indentlevel, =item stuff..., =back 🌈

Okay this trio is where things get spicy, because =over … =back regions can turn into a whole bunch of different DocBook constructs depending on the vibe. πŸ’…

The one thing to know up front: indentlevel gets completely ignored by Pod::2::DocBook. Every single time. That's a stylesheet problem, bestie, not a Pod problem. πŸŽ€

Indented text, no items, no problem πŸ¦‹

If you've got an =over … =back region with zero =items in it, that's just indented text, and it maps straight onto a DocBook blockquote element.

Feed it this:

=over 4

This text should be indented.

=back

And Pod::2::DocBook serves you back DocBook markup kinda like this:

<blockquote>
  <para>
    This text should be indented.
  </para>
</blockquote>

Lists go brrr 🌸

Now, once you're inside an =over … =back region, =item commands start generating lists. And here's the cute part β€” the text that follows the first =item is what decides which flavour of list you get. First item picks the whole aesthetic. ✨

  • * (an asterisk) β†’ <itemizedlist>
  • 1 or 1. β†’ <orderedlist numeration="arabic">
  • a or a. β†’ <orderedlist numeration="loweralpha">
  • A or A. β†’ <orderedlist numeration="upperalpha">
  • i or i. β†’ <orderedlist numeration="lowerroman">
  • I or I. β†’ <orderedlist numeration="upperroman">
  • anything else β†’ <variablelist> πŸ’€

And ngl, every single one of those outputs is relatively verbose, so the best way to actually see examples is to just render some Pod into DocBook yourself. Do it, it's giving hands-on learner. 🫢


=pod and =cut βœ‚οΈ

Pod::Parser recognizes these two, and because of that, so does Pod::2::DocBook. But plot twist β€” they don't produce any output at all. Silent. Mysterious. Iconic. 🀫


=begin formatname, =end formatname, =for formatname text... πŸ“¦

Pod::2::DocBook supports two formats, babes:

  • docbook β€” explained over in "Embedded DocBook Markup" πŸ’–
  • table β€” explained over in "Simple Tables" πŸŽ€

=encoding encodingname 😭

Bad news bestie: this command is currently not supported. If Pod::2::DocBook runs into a document that contains =encoding, it will straight up ignore the command and report an error:

unknown command `%s' at line %d in file %s

It said what it said. πŸ’€


πŸ¦‹ Embedded DocBook Markup πŸ¦‹

Okay so here's the tea: there are a wide range of DocBook structures that just have no Pod equivalent whatsoever. And for those, you're gonna have to bring your own markup, using either:

  • =begin docbook ... =end docbook
  • =for docbook ...

Pod::2::DocBook will output whatever text you hand it directly, unprocessed, which means it's 100% on you to make sure it's valid DocBook. No safety net, no vibe check, no takebacks. πŸ™ˆ

Images, footnotes and a whole bunch of inline elements are the obvious candidates for embedded markup. Another lil use case? Nesting sections more than four-deep. πŸ‘‘

Like, say your source looks like this:

=head1  1

This is Section 1

=head2 1.1

This is Section 1.1

=head3 1.1.1

This is Section 1.1.1

=head4 1.1.1.1

This is Section 1.1.1.1

=begin docbook

<section>
<title>1.1.1.1.1</title>
<para>This is Section 1.1.1.1.1</para>
</section>

=end docbook

Pod::2::DocBook will generate DocBook markup similar to this:

<section id="article-My-Article-1"><title>1</title>
  <para>
    This is Section 1
  </para>
  <section id="article-My-Article-1-1"><title>1.1</title>
    <para>
This is Section 1.1
    </para>
    <section id="article-My-Article-1-1-1"><title>1.1.1</title>
      <para>
This is Section 1.1.1
      </para>
      <section id="article-My-Article-1-1-1-1"><title>1.1.1.1</title>
        <para>
This is Section 1.1.1.1
        </para>
<section>
<title>1.1.1.1.1</title>
<para>This is Section 1.1.1.1.1</para>
</section>
      </section>
    </section>
  </section>
</section>

See how it just slotted your raw DocBook right in there? Nesting unlocked. πŸŽ‰


πŸŽ€ Simple Tables πŸŽ€

Pod::2::DocBook also gives you a lil mechanism for generating basic tables, using =begin table and =end docbook. (Yes, exactly like that, no typos from me, that's literally what it says. πŸ’…)

Got simple tabular data? Got a CSV file exported from some app? Pod::2::DocBook makes it easy to turn that into a table. The syntax is intentionally simple, so DocBook's entire table feature set is not represented here. But even if you need more complex table markup than Pod::2::DocBook produces, you can rapidly produce some markup, hand-edit it, and then embed it directly in your Pod with =begin docbook ... =end docbook. Workaround slay. ✨

Also heads up: every table definition spans multiple lines, so there is no equivalent =for table command. Periodt.

Here's the anatomy of a table def, bestie:

  1. The first line is the table's title. πŸ‘‘
  2. The second line is a list of comma-separated column specifications (really just column alignments), and each one can be left, center or right.
  3. The third line is a list of comma-separated column headings.
  4. Every line after that is comma-separated row data. πŸ“

And if any of your data actually contains commas? Wrap it in double quotes. And if it also contains double quotes? You gotta escape those inner quotes with backslashes. Typical CSV stuff, you know the drill. 😌

Here's an example:

=begin table

Sample Table
left,center,right
Powers of Ten,Planets,Dollars
10,Earth,$1
100,Mercury,$5
1000,Mars,$10
10000,Venus,$20
100000,"Jupiter, Saturn",$50

=end table

And here's what Pod::2::DocBook would do with it:

<table>
  <title>Sample Table</title>
  <tgroup cols="3">
    <colspec align="left">
    <colspec align="center">
    <colspec align="right">
    <thead>
      <row>
        <entry>Powers of Ten</entry>
        <entry>Planets</entry>
        <entry>Dollars</entry>
      </row>
    </thead>
    <tbody>
      <row>
        <entry>10</entry>
        <entry>Earth</entry>
        <entry>$1</entry>
      </row>
      <row>
        <entry>100</entry>
        <entry>Mercury</entry>
        <entry>$5</entry>
      </row>
      <row>
        <entry>1000</entry>
        <entry>Mars</entry>
        <entry>$10</entry>
      </row>
      <row>
        <entry>10000</entry>
        <entry>Venus</entry>
        <entry>$20</entry>
      </row>
      <row>
        <entry>100000</entry>
        <entry>Jupiter, Saturn</entry>
        <entry>$50</entry>
      </row>
    </tbody>
  </tgroup>
</table>

Look at that "Jupiter, Saturn" surviving the whole journey intact. Quoting works, babes. 🫢


πŸ’– Formatting Codes πŸ’–

Pod formatting codes render directly into DocBook as inline elements. No middleman, no drama. Here's the whole translation chart, bestie β€” memorize it or don't, it's your life. 😌

  • I<text> β†’
<emphasis role="italic">text</emphasis>
  • B<text> β†’
<emphasis role="bold">text</emphasis>
  • C<code> β†’
<literal role="code"><![CDATA[code]] ></literal>
  • L<name> β†’
<citerefentry><refentrytitle>name</refentrytitle></citerefentry>
  • L<name(n)> β†’
<citerefentry><refentrytitle>name</refentrytitle>
<manvolnum>n</manvolnum></citerefentry>
  • L<name/"sec"> or L<name/sec> β†’
<quote>sec</quote> in <citerefentry>
<refentrytitle>name</refentrytitle></citerefentry>
  • L<name(n)/"sec"> or L<name(n)/sec> β†’
<quote>sec</quote> in <citerefentry>
<refentrytitle>name</refentrytitle><manvolnum>n</manvolnum>
</citerefentry>
  • L</"sec"> or L</sec> or L<"sec"> β†’
<link linkend="article-My-Article-sec"><quote>sec</quote></link>
  • L<text|name> β†’
text
  • L<text|name/"sec"> or L<text|name/sec> β†’
text
  • L<text|/"sec"> or L<text|/sec> or L<text|"sec"> β†’
<link linkend="article-My-Article-sec"><quote>text</quote></link>
  • L<scheme:...> β†’
<ulink url="scheme:...">scheme:...</ulink>
  • E<verbar> β†’
|
  • E<sol> β†’
/
  • E<number> β†’
&#number;
  • any other E<escape> β†’
&escape;
  • F<filename> β†’
<filename>filename</filename>
  • S<text with spaces> β†’
text&nbsp;with&nbsp;spaces
  • X<topic name> β†’
<indexterm><primary>topic name</primary></indexterm>

That's the whole chart, bestie. Bookmark it, screenshot it, tattoo it, whatever works for you. πŸ’…βœ¨

πŸ” DIAGNOSTICS πŸ”

okay bestie, listen. Pod::2::DocBook is out here doing the absolute most to give you valid DocBook markup, even when your POD source is a whole mess. iconic behavior honestly. ✨

Any processing errors? They get noted in comments at the end of the output document. And here's the vibe: even when errors happen, Pod::2::DocBook always reads the entire input document and never exits with a non-zero status. She does not rage quit. She finishes the read. πŸ’…


🩷 the error messages, explained 🩷

  • unknown command %s' at line %d in file %s` Check "Command Paragraph" in perlpod for a list of valid commands. The command named in the error message was ignored. πŸ™ˆ
  • formatting code %s' nested within %s' at line %d in file %s See "Formatting Codes" in perlpod for the details on which formatting codes can actually be nested (not all of them, bestie). The offending code got translated into the output document as the raw text inside its angle brackets.
  • **unknown formatting code %s' at line in file %s** The input had a formatting code that isn't listed in perlpod`; it was translated into the output document as the raw text inside the angle brackets. (and yes, this string literally says "at line in file" with no number in it β€” that's just how it's written, no cap πŸ’€)
  • empty L<> at line %d in file %s Self-explanatory. πŸŽ€
  • invalid escape %s' at line %d in file %s` Also self-explanatory; it was translated into the output document as the raw text inside the angle brackets.
  • =item must be inside an =over ... =back section at line %d in file %s Self-explanatory again. The =item mentioned in the error was ignored.
  • `=end %s' found but current region opened with `=begin %s' The closest =end to the =begin it's complaining about didn't match. Processing just carried on as if the mismatched =end wasn't there. Moving on, not the drama we're entertaining today. πŸ¦‹
  • no matching `=end' for `=begin %s' Pod::2::DocBook hit the end of its input without ever finding an =end to match the =begin in the error. End-of-file processing continued.
  • unknown colspec %s' in table at line %d in file %s` See "Simple Tables" for a list of the supported column specifications.
  • encountered unknown state `%s' (this should never happen) The state here is an internal variable used to manage nested DocBook structures. You should genuinely never see this one. But if you do? Contact the module's author, fr fr. πŸ“£

🌈 SEE ALSO 🌈

DocBook related links: <http://www.docbook.org/>, <http://www.sagehill.net/docbookxsl/>, <http://developers.cogentrts.com/cogent/prepdoc/pd-axfrequentlyuseddocbooktags.html>


πŸ‘‘ AUTHOR πŸ‘‘

Alligator Descartes <descarte@symbolstone.org> wrote a module called Pod::2::DocBook, which was later maintained by Jan Iven <jan.iven@cern.ch>. That module was based on the original pod2html by Tom Christiansen <tchrist@mox.perl.com>.

Nandu Shah <nandu@zvolve.com> wrote Pod::DocBook, which is unrelated to the previous module (even though they both perform the same function, which is kind of a whole thing πŸ™ˆ). (<http://search.cpan.org/~nandu/Pod-DocBook-1.2/>)

Jozef Kutej <jkutej@cpan.org> renamed the module to Pod::2::DocBook because Nandu's version was buried in the CPAN archive as an "UNAUTHORIZED RELEASE". πŸ’€ iconic origin story actually.


Copyright 2004, Nandu Shah <nandu@zvolve.com>

Copyright 2008, Jozef Kutej <jkutej@cpan.org>

This library is free software; you may redistribute it and/or modify it under the same terms as Perl itself. 🫢


and that's the whole page bestie!! πŸ’– this one came out with perl v5.30.0, dated 2020-05-17, on the Pod::2::DocBook(3pm) page β€” go read some POD and make some gorgeous DocBook, mwah πŸ’…βœ¨πŸŒΈ

πŸ“¦ where this page comes from