podlinkcheck -- check Perl pod L<> link references
podlinkcheck [--options] file-or-dir...
The command line options are
Print a command line summary.
Add an extra directory to look for target modules.
Print more about program operation (including CPAN loading).
Print the program version number and exit.
PodLinkCheck parses Perl POD from a script, module or documentation and checks that L<> links within it refer to a known program, module, or man page.
L<>
L<foo> check module, pod or program "foo" L<foo/section> and check section within the pod L<bar(1)> check man page "bar(1)"
The command line is either individual files or whole directories. For a directory all the .pl, .pm and .pod files under it are checked. So for example to churn through all installed add-on modules,
podlinkcheck /usr/share/perl5
Bad links are usually typos in the module name or section name, or sometimes L<display|target> parts the wrong way around. Occasionally there may be an L<foo> used where just markup C<> or I<> was intended.
L<display|target>
L<foo>
C<>
I<>
External links are checked by seeking the target .pm module or .pod documentation in the @INC path (per Pod::Find), or seeking a script (no file extension) in the usual executable PATH. A section name in a link is checked by parsing the POD in the target file.
@INC
PATH
If a module is not installed in @INC or extra -I directories then its existence is also checked in the CPAN indexes with App::cpanminus, CPAN::SQLite, CPAN or CPANPLUS. Nothing is downloaded, just current data consulted. A warning is given if a section name in a link goes unchecked because it's on CPAN but not available locally.
-I
App::cpanminus
CPAN::SQLite
CPAN
CPANPLUS
If checking your own work then most likely you will have copies of cross-referenced modules installed (having compared or tried them). In that sense the CPAN index lookups are a fallback.
Manpage links are checked by asking the man program if it recognises the name, including any number part like chmod(2). A manpage can also satisfy what otherwise appears to be a POD link with no sub-section, since there's often some confusion between the two.
man
chmod(2)
Internal links are sometimes written
L<SYNOPSIS> # may be ambiguous
but the Perl 5.10 perlpodspec advice is to avoid ambiguity between an external module and a one-word internal section by writing a section with / or quotes,
perlpodspec
See L</SYNOPSIS> above. # good See L<"SYNOPSIS"> above. # good
podlinkcheck warns about L<SYNOPSIS> section links. But not if it's both an valid external module and internal section -- because it's not uncommon to have a module name as a heading or item and an L<> link still meaning the external one.
podlinkcheck
L<SYNOPSIS>
An L<> section name can use just the first word of an item or heading. This is how Pod::Checker behaves and it's good for perlfunc cross references where just the function name can be given without the full argument list of the =item. Eg.
Pod::Checker
perlfunc
=item
L<perlfunc/split>
The first word is everything up to the first whitespace. This doesn't come out very well on a target like =item somefun( ARG ), but it's how Pod::Checker 1.45 behaves. If the targets are your own then you might make the first word or full item something sensible to appear in an L<>.
=item somefun( ARG )
If a target section is not found then podlinkcheck will try to suggest something close, eg. differing only in punctuation or upper/lower case. Some of the POD translators may ignore upper/lower case anyway, but it's good to write an L<> the same as the actual target.
foo.pl:130:31: no section "constructor" in "CHI" (file /usr/share/perl5/CHI.pm) perhaps it should be "CONSTRUCTOR"
For reference, numbered =item section names go in an L<> without the number. This is good since the numbering might change. If podlinkcheck suggests a number in a target then it may be a mistake in the target document. A numbered item should have the number alone on the =item and the section name as the next paragraph.
=item 1. # good The First Thing # the section name Paragraph about this thing. =item 2. The Second Thing # bad Paragraph about this next thing.
The second item "2. The Second Thing" is not a numbered item for POD purposes, but rather text that happens to start with a number. Of course sometimes that's what you want, eg.
=item 64 Bit Support
podlinkcheck uses Pod::Simple for parsing and so follows its interpretation of the various hairy L<> link forms. If an L<> appears to be mis-interpreted you might rewrite or add some escapes (like E<sol>) for the benefit of all translators which use Pod::Simple. In Perl 5.10 that includes the basic pod2man.
Pod::Simple
pod2man
podchecker (the Pod::Checker module) checks internal links, but it doesn't check external links.
podchecker
Test::Pod::LinkCheck is similar in a .t test framework. It uses some of PodLinkCheck but different reporting and a stricter approach to dubious POD.
Test::Pod::LinkCheck
The search path for installed scripts.
HOME
Used by the various CPAN modules for ~/.cpan etc directories.
~/.cpan
PERL5LIB
The usual extra Perl module directories (see "ENVIRONMENT" in perlrun), which become @INC where link targets are sought.
App::cpanminus is checked first since it's a bsearch of 02packages.details.txt, and CPAN::SQLite second since it's a database lookup. But if a target is not found there then the full CPAN and CPANPLUS caches are loaded and checked. This might use a fair bit of memory for a non-existent target, but it's also possible they're more up-to-date.
No attempt is made to tell which of the indexes is the most up-to-date. If a module has been renamed (bad) then it may still exist in an old index. The suggestion is to avoid having old stuff lying around (including old mirror files in App::cpanminus).
The code consulting CPAN.pm may need a tolerably new version of that module, maybe 1.61 circa Perl 5.8.0. On earlier versions its index is not used.
CPAN.pm
The line:column number reported for an offending L<> is found by some gambits extending what Pod::Simple normally records. There's a chance it could be a little off within the paragraph.
Pod::Simple prior to version 3.24 didn't allow dots "." in man-page names, resulting in for example login.conf(5) being treated as a Perl module name not a man page name. If you have such links then Pod::Simple 3.24 up is recommended.
Directories are currently traversed using File::Find::Iterator. It follows symlinks but neither its version 0.4 nor PodLinkCheck guard against infinite descent into symlink cycles. The intention perhaps would be follow all symlinks to files, but follow to a directory just once as protection against cycles.
~/.cpanm/sources/*/02packages.details.txt files from App::cpanminus
~/.cpan/cpandb.sql used by CPAN::SQLite
~/.cpan/Metadata used by CPAN
~/.cpanplus/* variously used by CPANPLUS
podchecker, podlint
Pod::Simple, Pod::Find, CPAN, CPAN::SQLite, CPANPLUS, cpanm
Test::Pod::LinkCheck, Pod::Checker, Test::Pod
http://user42.tuxfamily.org/podlinkcheck/index.html
Copyright 2010, 2011, 2012, 2013, 2016 Kevin Ryde
PodLinkCheck is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
PodLinkCheck is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with PodLinkCheck. If not, see <http://www.gnu.org/licenses/>.
To install podlinkcheck, copy and paste the appropriate command in to your terminal.
cpanm
cpanm podlinkcheck
CPAN shell
perl -MCPAN -e shell install podlinkcheck
For more information on module installation, please visit the detailed CPAN module installation guide.