File Coverage

blib/lib/Pandoc/Filter/Multifilter.pm
Criterion Covered Total %
statement 30 58 51.7
branch 6 22 27.2
condition 5 22 22.7
subroutine 8 11 72.7
pod 4 4 100.0
total 53 117 45.3


line stmt bran cond sub pod time code
1             package Pandoc::Filter::Multifilter;
2 1     1   1020 use strict;
  1         2  
  1         36  
3 1     1   5 use warnings;
  1         2  
  1         31  
4 1     1   38 use 5.010;
  1         3  
5              
6             our $VERSION = '0.34';
7              
8 1     1   6 use parent 'Pandoc::Filter';
  1         2  
  1         7  
9             our @EXPORT_OK = (qw(find_filter apply_filter));
10              
11 1     1   67 use Pandoc::Elements 'pandoc_json';
  1         2  
  1         44  
12 1     1   837 use IPC::Cmd 'can_run';
  1         52422  
  1         77  
13 1     1   14 use IPC::Run3;
  1         3  
  1         723  
14              
15             sub new {
16 0     0 1 0 bless { }, shift;
17             }
18              
19             sub apply {
20 0     0 1 0 my ( $self, $doc, $format, $meta ) = @_;
21 0 0       0 return $doc if $doc->name ne 'Document';
22              
23 0         0 my $multi = $doc->meta->{multifilter};
24 0 0 0     0 return $doc if !$multi or $multi->name ne 'MetaList';
25              
26             my @filters = map {
27 0 0 0     0 if ($_->name eq 'MetaMap' and $_->{filter}) {
    0 0        
28 0         0 $_->value
29             } elsif ($_->name eq 'MetaString' or $_->name eq 'MetaInlines') {
30 0         0 { filter => $_->value }
31             }
32 0         0 } @{$multi->content};
  0         0  
33              
34 0         0 foreach (@filters) {
35 0         0 my @filter = find_filter($_->{filter});
36 0         0 apply_filter($doc, $format, @filter);
37             }
38              
39 0         0 $doc;
40             }
41              
42             our %SCRIPTS = (
43             hs => 'runhaskell',
44             js => 'node',
45             php => 'php',
46             pl => 'perl',
47             py => 'python',
48             rb => 'ruby',
49             );
50              
51             sub find_filter {
52 4     4 1 128841 my $name = shift;
53 4   33     28 my $data_dir = shift // $ENV{HOME} . '/.pandoc';
54 4         12 $data_dir =~ s|/$||;
55              
56 4         16 foreach my $filter ("$data_dir/filters/$name", $name) {
57 8 100       184 return $filter if -x $filter;
58 7 100 66     86 if (-e $filter and $filter =~ /\.([a-z]+)$/i) {
59 1 50       12 if ( my $cmd = $SCRIPTS{lc($1)} ) {
60 1 50       7 die "cannot execute filter with $cmd\n" unless can_run($cmd);
61 1         539 return ($cmd, $filter);
62             }
63             }
64             }
65              
66 2   100     11 return (can_run($name) or die "filter not found: $name\n");
67             }
68              
69             sub apply_filter {
70 0     0 1   my ($doc, $format, @filter) = @_;
71              
72 0           my $stdin = $doc->to_json;
73 0           my $stdout = "";
74 0           my $stderr = "";
75              
76 0   0       run3 [@filter, $format // ''], \$stdin, \$stdout, \$stderr;
77 0 0         if ($?) {
78 0 0 0       $stderr .= "\n" if $stderr ne '' and $stderr !~ /\n\z/s;
79 0           die join(' ','filter failed:',@filter)."\n$stderr";
80             }
81              
82 0           my $transformed = eval { pandoc_json($stdout) };
  0            
83 0 0         die join(' ','filter emitted no valid JSON:',@filter)."\n" if $@;
84              
85             # modify original document
86 0           $doc->meta($transformed->meta);
87 0           $doc->content($transformed->content);
88              
89 0           return $doc;
90             }
91              
92             __END__