File Coverage

blib/lib/App/pod2pandoc.pm
Criterion Covered Total %
statement 47 94 50.0
branch 6 40 15.0
condition 3 23 13.0
subroutine 13 17 76.4
pod 2 2 100.0
total 71 176 40.3


line stmt bran cond sub pod time code
1             package App::pod2pandoc;
2 4     4   59509 use strict;
  4         7  
  4         99  
3 4     4   11 use warnings;
  4         6  
  4         88  
4 4     4   84 use 5.010;
  4         13  
5              
6             our $VERSION = '0.3.2';
7              
8 4     4   2650 use Getopt::Long qw(:config pass_through);
  4         34312  
  4         21  
9 4     4   2867 use Pod::Usage;
  4         119660  
  4         551  
10 4     4   1717 use Pod::Simple::Pandoc;
  4         9  
  4         140  
11 4     4   18 use Pandoc;
  4         4  
  4         22  
12 4     4   294 use Pandoc::Elements;
  4         6  
  4         818  
13 4     4   19 use Scalar::Util qw(reftype blessed);
  4         6  
  4         164  
14 4     4   17 use JSON;
  4         5  
  4         37  
15 4     4   307 use Carp;
  4         4  
  4         163  
16              
17 4     4   15 use parent 'Exporter';
  4         5  
  4         28  
18             our @EXPORT = qw(pod2pandoc);
19             our @EXPORT_OK = qw(pod2pandoc parse_arguments);
20              
21             sub parse_arguments {
22 2     2 1 11 my %opt;
23 2 50       14 Getopt::Long::GetOptionsFromArray(
24             \@_, \%opt, 'help|h|?', 'parse=s',
25             'podurl=s', 'ext=s', 'index=s', 'wiki',
26             'default-meta=s', 'update', 'quiet'
27             ) or exit 1;
28 2 50       1318 pod2usage(1) if delete $opt{help};
29              
30 2 50       8 my @input = @_ ? () : '-';
31              
32 2         7 my ($index) = grep { $_[$_] eq '--' } ( 0 .. @_ - 1 );
  9         18  
33              
34 2 100       6 if ( defined $index ) {
35 1         8 push @input, shift @_ for 0 .. $index - 1;
36 1         3 shift @_; # --
37             }
38             else {
39 1   66     21 push( @input, shift @_ ) while @_ and $_[0] !~ /^-./;
40             }
41              
42 2 50 33     9 if ( $opt{parse} and $opt{parse} ne '*' ) {
43 0         0 $opt{parse} = [ split /[, ]+/, $opt{parse} ];
44             }
45              
46 2         28 return ( \@input, \%opt, @_ );
47             }
48              
49             # TODO: move to Pandoc::Elements
50             sub _add_default_meta {
51 0     0     my ( $doc, $meta ) = @_;
52 0 0         return unless $meta;
53 0   0       $doc->meta->{$_} //= $meta->{$_} for keys %$meta;
54             }
55              
56             sub _plain2meta {
57 0     0     my $value = shift;
58 0 0         if ( !ref $value ) {
    0          
    0          
    0          
59 0           MetaString $value;
60             }
61             elsif ( JSON::is_bool($value) ) {
62 0           MetaBool $value;
63             }
64             elsif ( blessed($value) ) {
65 0 0 0       if ( $value->can('is_meta') and $value->is_meta ) {
66 0           $value;
67             }
68             else {
69 0           MetaString "$value";
70             }
71             }
72             elsif ( reftype $value eq 'ARRAY' ) {
73 0           MetaList [ map { _plain2meta($_) } @$value ];
  0            
74             }
75             else {
76             MetaMap {
77 0           map { $_ => _plain2meta( $value->{$_} ) } keys %$value
  0            
78             }
79             }
80             }
81              
82             sub _default_meta {
83 0   0 0     my $meta = shift || {};
84 0 0         return $meta if ref $meta;
85              
86             # read default metadata from file
87 0 0         if ( $meta =~ /\.json$/ ) {
88 0 0         open( my $fh, "<:encoding(UTF-8)", $meta )
89             or croak "failed to open $meta";
90 0           local $/;
91 0           $meta = decode_json(<$fh>);
92 0           for ( keys %$meta ) {
93 0           $meta->{$_} = _plain2meta( $meta->{$_} );
94             }
95 0           return $meta;
96             }
97             else {
98 0           pandoc->require('1.12.1');
99 0           return pandoc->file($meta)->meta;
100             }
101             }
102              
103             sub pod2pandoc {
104 0     0 1   my $input = shift;
105 0 0         my $opt = ref $_[0] ? shift : {};
106 0           my @args = @_;
107              
108             $opt->{meta} =
109 0   0       _default_meta( $opt->{meta} // delete $opt->{'default-meta'} );
110              
111             # directories
112 0 0 0       if ( @$input > 0 and -d $input->[0] ) {
113 0 0         my $target = @$input > 1 ? pop @$input : $input->[0];
114              
115 0           my $modules = Pod::Pandoc::Modules->new;
116 0           foreach my $dir (@$input) {
117 0           my $found = Pod::Simple::Pandoc->new->parse_modules($dir);
118             warn "no .pm, .pod or Perl script found in $dir\n"
119 0 0 0       unless %$found or $opt->{quiet};
120 0           $modules->add( $_ => $found->{$_} ) for keys %$found;
121             }
122              
123 0           _add_default_meta( $modules->{$_}, $opt->{meta} ) for %$modules;
124              
125 0           $modules->serialize( $target, $opt, @args );
126             }
127              
128             # files and/or module names
129             else {
130 0           my $parser = Pod::Simple::Pandoc->new(%$opt);
131 0 0         my $doc = $parser->parse_and_merge( @$input ? @$input : '-' );
132              
133 0           _add_default_meta( $doc, $opt->{meta} );
134              
135 0 0         if (@args) {
136 0           pandoc->require('1.12.1');
137 0           $doc->pandoc_version( pandoc->version );
138 0           print $doc->to_pandoc(@args);
139             }
140             else {
141 0           print $doc->to_json, "\n";
142             }
143             }
144             }
145              
146             1;
147             __END__