File Coverage

blib/lib/App/sdview/Output/Markdown.pm
Criterion Covered Total %
statement 98 108 90.7
branch 9 10 90.0
condition 1 2 50.0
subroutine 17 19 89.4
pod 0 9 0.0
total 125 148 84.4


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2021-2023 -- leonerd@leonerd.org.uk
5              
6 2     2   996 use v5.26;
  2         9  
7 2     2   11 use warnings;
  2         4  
  2         67  
8              
9 2     2   13 use Object::Pad 0.800;
  2         15  
  2         89  
10              
11             package App::sdview::Output::Markdown 0.13;
12             class App::sdview::Output::Markdown
13             :does(App::sdview::Output)
14 1     1   582 :strict(params);
  1         2  
  1         46  
15              
16 2     2   510 use String::Tagged::Markdown 0.02;
  2         38  
  2         67  
17              
18 2     2   12 use constant format => "Markdown";
  2         16  
  2         4511  
19              
20             =head1 NAME
21              
22             C - generate Markdown output from L
23              
24             =head1 SYNOPSIS
25              
26             $ sdview README.pod -o Markdown > README.md
27              
28             =head1 DESCRIPTION
29              
30             This output module adds to L the ability to output text in
31             Markdown formatting. Given a Markdown file as input, the output should be
32             relatively similar, up to minor details like whitespacing. Given input in some
33             other format, it will do a reasonable job attempting to represent most of the
34             structure and formatting.
35              
36             =cut
37              
38 2     2 0 17 method output_head1 ( $para ) { $self->_output_head( "#", $para ); }
  2         4  
  2         4  
  2         2  
  2         6  
39 1     1 0 3 method output_head2 ( $para ) { $self->_output_head( "##", $para ); }
  1         2  
  1         3  
  1         2  
  1         3  
40 0     0 0 0 method output_head3 ( $para ) { $self->_output_head( "###", $para ); }
  0         0  
  0         0  
  0         0  
  0         0  
41 0     0 0 0 method output_head4 ( $para ) { $self->_output_head( "####", $para ); }
  0         0  
  0         0  
  0         0  
  0         0  
42              
43 3         5 method _output_head ( $leader, $para )
  3         7  
  3         3  
  3         4  
44 3     3   6 {
45 3         12 $self->maybe_blank;
46              
47 3         14 $self->say( $leader, " ", $self->_convert_str( $para->text ) );
48             }
49              
50 6         19 method output_plain ( $para )
  6         11  
  6         8  
51 6     6 0 11 {
52 6         19 $self->maybe_blank;
53              
54 6         16 $self->say( $self->_convert_str( $para->text ) );
55             }
56              
57 1         3 method output_verbatim ( $para )
  1         2  
  1         2  
58 1     1 0 2 {
59 1         4 $self->maybe_blank;
60              
61             # TODO: Offer a choice of ``` vs indented
62              
63 1   50     6 $self->say( "```" . ( $para->language // "" ) );
64 1         14 $self->say( $para->text );
65 1         10 $self->say( "```" );
66             }
67              
68 1     1 0 3 method output_list_bullet ( $para ) { $self->_output_list( $para ); }
  1         2  
  1         2  
  1         2  
  1         5  
69 1     1 0 4 method output_list_number ( $para ) { $self->_output_list( $para ); }
  1         2  
  1         2  
  1         2  
  1         3  
70              
71 2         3 method _output_list ( $para )
  2         3  
  2         4  
72 2     2   4 {
73 2         7 $self->maybe_blank;
74              
75 2         10 my $n = $para->initial;
76 2         8 foreach my $item ( $para->items ) {
77 6         8 my $leader;
78              
79 6 100       19 if( $para->listtype eq "bullet" ) {
    50          
80 3         7 $leader = "*";
81             }
82             elsif( $para->listtype eq "number" ) {
83 3         15 $leader = sprintf "%d.", $n++;
84             }
85              
86 6         25 $self->say( $leader, " ", $self->_convert_str( $item->text ) );
87             }
88             }
89              
90 2         3 method output_table ( $para )
  2         6  
  2         3  
91 2     2 0 5 {
92 2         7 $self->maybe_blank;
93              
94 2         5 my @rows = $para->rows;
95              
96 2         4 my $first = 1;
97 2         5 foreach my $row ( @rows ) {
98 3         7 my @cells = @$row;
99 3         8 $self->say( join "|", "", ( map { " " . $self->_convert_str( $_->text ) . " " } @cells ), "" );
  7         776  
100              
101 3 100       20 next unless $first;
102              
103             my @aligns = map {
104 2         10 my $n = length $_->text;
  5         15  
105 5 100       35 $_->align eq "centre" ? ":".("-"x($n-2)).":" :
    100          
106             $_->align eq "right" ? ("-"x($n-1)).":" :
107             ("-"x $n );
108             } @cells;
109 2         5 $self->say( join "|", "", ( map { " $_ " } @aligns ), "" );
  5         18  
110 2         9 undef $first;
111             }
112             }
113              
114 22         29 method _convert_str ( $s )
  22         33  
  22         29  
115 22     22   38 {
116 1         3 return String::Tagged::Markdown->clone( $s,
117             only_tags => [qw( bold italic monospace strikethrough file link )],
118             convert_tags => {
119             # bold, italic remain as they are
120             monospace => "fixed",
121             strikethrough => "strike",
122             file => "italic", # There isn't a "filename" format in Markdown
123 1     1   2 link => sub ($t, $v) { return link => $v->{target} },
  1         4  
  1         78  
  1         2  
124             }
125 22         172 )->build_markdown;
126             }
127              
128             =head1 AUTHOR
129              
130             Paul Evans
131              
132             =cut
133              
134             0x55AA;