00001 package Doxygen::POD::Item;
00002
00003 =head1 NAME
00004
00005 Doxygen::POD::Item - Perl extension for generating Doxygen documentation
00006
00007 =head1 SYNOPSIS
00008
00009 my $item = new Doxygen::POD::Item;
00010
00011 =head1 ABSTRACT
00012
00013 A simple item in a POD source file.
00014
00015 =head1 DESCRIPTION
00016
00017 =head1 METHODS
00018
00019 =over
00020
00021 =cut
00022
00023 use 5.005; # just to pick something, but not really tested
00024 use strict;
00025 use warnings;
00026 use UNIVERSAL qw(can isa);
00027
00028 use base qw(Doxygen::Item);
00029
00030 our $VERSION = '0.01';
00031
00032 use constant HTML_CONVERT => 1;
00033
00034 ###########################################################################
00035 ###########################################################################
00036
00037 =item C<massage($self, $source)>
00038
00039 Convert all the comment text in this block from POD formatting
00040 sequences into Doxygen formatting sequences.
00041
00042 =over
00043
00044 =item filename
00045
00046 F<filename.txt>
00047
00048 =item italics
00049
00050 I<italicized>
00051
00052 =item boldface
00053
00054 B<boldface>
00055
00056 =item fixed pitch
00057
00058 C<typewriter>
00059
00060 =item special characters
00061
00062 Numeric characters 'E<49>', 'E<062>', 'EZ<><0x33>>'.
00063 Named characters 'E<lt>', 'E<gt>', 'E<sol>',
00064 'E<verbar>', 'E<amp>'.
00065
00066 =item spaces
00067
00068 Non-breaking spacing:
00069 S<good boys drink milk until it comes out of their ears>.
00070
00071 =item null sequence
00072
00073 Dreaded 'Z' sequence: BZ<><null>.
00074
00075 =item links
00076
00077 L<simple>, L<more|complex>, L<to/section>,
00078 L<more I<complex> yet|linkage>, L<text|/local>,
00079 L<http:
00080
00081 =back
00082
00083 =cut
00084
00085 sub massage # $self, $source
00086 {
00087 my ($self, $source) = @_;
00088
00089 return unless isa $self->text('comment'), 'ARRAY';
00090
00091 my $text = '';
00092 my @text = ( );
00093
00094 $self->{name} = _doxify_($source, $self->{name})
00095 if $self->{name};
00096
00097 for (@{$self->text('comment')}) {
00098 if (ref($_)) {
00099 if ($text) {
00100 $text = _doxify_($source, $text);
00101 push @text, map { "$_\n" } split /\n/, $text;
00102 $text = '';
00103 }
00104
00105 $_->massage($source) if can $_, 'massage';
00106
00107 push @text, $_;
00108 } else {
00109 $text .= $_;
00110 }
00111 }
00112
00113 if ($text) {
00114 $text = _doxify_($source, $text);
00115 push @text, map { "$_\n" } split /\n/, $text;
00116 }
00117
00118 $self->textClear('comment');
00119 $self->textAppend('comment', @text);
00120 }
00121
00122 ###########################################################################
00123 ###########################################################################
00124
00125 =item C<generate($self, %flags)>
00126
00127 Generates output understandable by doxygen to standard output.
00128
00129 =cut
00130
00131 sub generate # $self, %flags
00132 {
00133 my ($self, %flags) = @_;
00134 my $which = $flags{which} || 'text';
00135
00136 return
00137 unless $self->text($which)
00138 || ($which ne 'text' &&
00139 $self->text($which = 'text'));
00140
00141 unless (isa($self->text($which), 'ARRAY')) {
00142 warn "$which items for $self not an array reference\n";
00143 next;
00144 }
00145
00146 $flags{which} = $which unless $flags{which};
00147
00148 unless ($self->{name}) {
00149 # No name, not a list item
00150 } elsif ($flags{named}) {
00151 # This is part of a set of named definitions:
00152 Doxygen::Item::genThing("<dt>$self->{name}</dt><dd>\n", %flags)
00153 } else {
00154 # Just a plain ole' list item:
00155 Doxygen::Item::genThing("<li>\n", %flags)
00156 }
00157
00158 # The goop inside the item:
00159 my $first = 1;
00160
00161 for (@{$self->text($which)}) {
00162 next
00163 if $first
00164 && ! ref($_)
00165 && ! ($_ && $_ =~ /\S/);
00166
00167 Doxygen::Item::genThing($_, %flags);
00168 undef $first;
00169 }
00170
00171 # Terminate definition if necessary:
00172 Doxygen::Item::genThing("</dd>\n", %flags)
00173 if $self->{name}
00174 && $flags{named};
00175 }
00176
00177 ###########################################################################
00178 ###########################################################################
00179
00180 =item C<_doxify_($source, $text)>
00181
00182 Convert POD escape sequences to HTML escape sequences.
00183
00184 Also protects Doxygen escape sequences.
00185
00186 =cut
00187
00188 sub _doxify_
00189 {
00190 my ($source, $text) = @_;
00191 my $result = '';
00192
00193 # $source->log('W', '_doxify_(', $source, ', ', $text, ')');
00194 # $source->pushLog;
00195
00196 # Protect Doxygen escape sequences:
00197
00198 $text =~ s/([\\\@])/$1$1/gs;
00199
00200 # Convert POD escape sequences:
00201
00202 while ($text =~ s/^(.*?)([BCEFILSZ])<
00203 $result .= $1;
00204
00205 my $code = $2;
00206 my $cnt = 1;
00207
00208 $cnt++
00209 while $text =~ s/^<
00210
00211 my $end = index $text, '>' x $cnt;
00212
00213 if ($end < 0) {
00214 $source->log('W', 'Unterminated POD escape sequence ',
00215 $code, '<' x $cnt, substr($text, 0, 15), '...');
00216 next;
00217 }
00218
00219 my $inner = substr($text, 0, $end, '');
00220
00221 substr($text, 0, $cnt) = '';
00222
00223 if ($code eq 'B') {
00224 $result .= HTML_CONVERT
00225 ? "<strong>$inner</strong>"
00226 : _glom_('@b', $inner);
00227 } elsif ($code eq 'C' || $code eq 'F') {
00228 $result .= HTML_CONVERT
00229 ? "<tt>$inner</tt>"
00230 : _glom_('@c', $inner);
00231 } elsif ($code eq 'E') {
00232 $result .= _escape_($inner);
00233 } elsif ($code eq 'I') {
00234 $result .= HTML_CONVERT
00235 ? "<em>$inner</em>"
00236 : _glom_('@e', $inner);
00237 } elsif ($code eq 'L') {
00238 $result .= _linkage_($inner);
00239 } elsif ($code eq 'S') {
00240 $result .= _spaces_($inner);
00241 } elsif ($code eq 'Z') {
00242 $result .= $inner;
00243 } else {
00244 my $orig = "$code<$inner>";
00245
00246 $source->log('W', 'Unknown POD escape sequence ', $orig);
00247 $result .= $orig;
00248 }
00249 }
00250
00251 $result .= $text;
00252
00253 # $source->log('T', 'Result: ', $result);
00254 # $source->popLog;
00255
00256 $result
00257 }
00258
00259 ###########################################################################
00260
00261 my %_html_ = (
00262 gt => '>',
00263 lt => '<',
00264 sol => '/',
00265 verbar => '|',
00266 );
00267 my %_doxy_ = (
00268 %_html_, # defaults, where necessary, overridden by:
00269 gt => '\\>',
00270 lt => '\\<',
00271 # sol => '/',
00272 # verbar => '|',
00273 );
00274
00275 sub _escape_ # $which
00276 {
00277 my $which = shift;
00278 my $char = undef;
00279
00280 if ($which =~ m|^0[0-7]+$|) {
00281 # Character with specified number in octal:
00282 $char = oct($which);
00283 } elsif ($which =~ m|^0x[0-9A-F]+$|) {
00284 # Character with specified number in hex:
00285 $char = hex($which);
00286 } elsif ($which =~ m|^\d+$|i) {
00287 # Character with specified number in decimal:
00288 $char = int($which);
00289 }
00290
00291 return ($char >= 32 && $char < 255) ? chr($char) : "&#$char;"
00292 if defined $char;
00293
00294 my $lookup = HTML_CONVERT ? \%_html_ : \%_doxy_;
00295
00296 $lookup->{$which} || "&$which;"
00297 }
00298
00299 ###########################################################################
00300
00301 sub _glom_ # $prefix, $text
00302 {
00303 my ($prefix, $text) = @_;
00304
00305 join '', map {
00306 /\S/ ? "$prefix $_" : $_
00307 } split m|(\s+)|, $text
00308 }
00309
00310 ###########################################################################
00311
00312 sub _linkage_ # $link
00313 {
00314 my $link = shift;
00315
00316 return $link;
00317
00318 return HTML_CONVERT ? "<a href='$link'>$link</a>" : $link
00319 if $link =~ m{^\w+:};
00320
00321 my $sect = undef;
00322 my $text = undef;
00323
00324 ($link, $text) = ($2, $1)
00325 if $link =~ m{^(.*?)\|(.*)$};
00326
00327 ($link, $sect) = ($1, $2)
00328 if $link =~ m{^(.*?)/(.*)$};
00329
00330 $text = $sect || $link
00331 unless $text;
00332
00333 $link = "$link#$sect"
00334 if $sect;
00335
00336 HTML_CONVERT ? "\{(a href='$link')\}$text\{(/a)\}" : $text
00337 }
00338
00339 ###########################################################################
00340
00341 sub _spaces_ # $text
00342 {
00343 my ($text) = @_;
00344
00345 join '', map {
00346 $_ ne ' ' ? $_ :
00347 HTML_CONVERT ? ' '
00348 : chr(0xA0)
00349 } split m|( )|, $text
00350 }
00351
00352 ###########################################################################
00353 ###########################################################################
00354
00355 1
00356
00357 __END__
00358
00359 =back
00360
00361 =head1 SEE ALSO
00362
00363 DoxyFilt.pl Doxygen::Item
00364
00365 =head1 AUTHOR
00366
00367 Marc M. Adkins, L<mailTo:Perl@Doorways.org>
00368
00369 =head1 COPYRIGHT AND LICENSE
00370
00371 Copyright 2004 by Marc M. Adkins
00372
00373 This library is free software; you can redistribute it and/or modify
00374 it under the same terms as Perl itself.
00375
00376 =cut