File Coverage

blib/lib/App/sdview/Parser/Markdown.pm
Criterion Covered Total %
statement 114 126 90.4
branch 37 42 88.1
condition 20 27 74.0
subroutine 13 15 86.6
pod 0 4 0.0
total 184 214 85.9


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-2022 -- leonerd@leonerd.org.uk
5              
6 4     4   473775 use v5.26;
  4         30  
7 4     4   28 use warnings;
  4         9  
  4         132  
8              
9 4     4   1226 use Object::Pad 0.800;
  4         19442  
  4         263  
10              
11             package App::sdview::Parser::Markdown 0.13;
12             class App::sdview::Parser::Markdown
13             :does(App::sdview::Parser)
14 2     2   1174 :strict(params);
  2         8  
  2         99  
15              
16 4     4   3065 use File::Slurper 'read_text';
  4         12631  
  4         301  
17              
18 4     4   2098 use String::Tagged::Markdown;
  4         11583  
  4         178  
19              
20 4     4   29 use constant format => "Markdown";
  4         9  
  4         274  
21 4     4   29 use constant sort_order => 20;
  4         8  
  4         12982  
22              
23             =head1 NAME
24              
25             C - parse Markdown files for L
26              
27             =head1 SYNOPSIS
28              
29             $ sdview README.md
30              
31             $ sdview -f Markdown my-document
32              
33             =head1 DESCRIPTION
34              
35             This parser module adds to L the ability to parse input text in
36             Markdown formatting.
37              
38             It uses a custom in-built parser for the block-level parts of the formatting,
39             able to handle comments, verbatim blocks, headings in both C<#>-prefixed and
40             C<=>-underlined styles, bullet and numbered lists, and tables.
41              
42             It uses L to parse the inline-level formatting,
43             supporting bold, italic, strikethrough, and fixed-width styles, and links.
44              
45             =cut
46              
47 0     0 0 0 sub find_file ( $class, $name ) { return undef }
  0         0  
  0         0  
  0         0  
  0         0  
48              
49 1         4 sub can_parse_file ( $class, $file )
50 1     1 0 6552 {
  1         2  
  1         2  
51 1         11 return $file =~ m/\.(?:md|markdown)$/;
52             }
53              
54 0         0 method parse_file ( $fh )
  0         0  
  0         0  
55 0     0 0 0 {
56 0         0 return $self->parse_string( read_text $fh );
57             }
58              
59             field @_paragraphs;
60              
61             sub _split_table_row ( $str )
62 16     16   122 {
  16         29  
  16         23  
63 16 50       70 $str =~ m/^\s*\|/ or return undef;
64 16 50       75 $str =~ m/\|\s*$/ or return undef;
65              
66 16         110 my @cols = split m/\|/, $str, -1;
67 16         31 shift @cols; pop @cols;
  16         32  
68              
69 16         133 s/^\s+//, s/\s+$// for @cols;
70              
71 16         94 return \@cols;
72             }
73              
74 16         27 method parse_string ( $str )
  16         29  
  16         24  
75 16     16 0 39 {
76 16         30 my $in_verb;
77              
78             my @lines;
79              
80 16         81 foreach ( split( m/\n/, $str ), "" ) {
81 109         184 my $line = $_; # So we have a copy, because foreach my ... will alias the readonly ""
82              
83 109 100       204 if( $in_verb ) {
84 8         34 my $para = $_paragraphs[-1];
85              
86 8 100       31 if( $line =~ m/^\`\`\`/ ) {
87 2         17 undef $in_verb;
88             next
89 2         6 }
90              
91 6 100       19 length $para->text and
92             $para->text->append( "\n" );
93              
94 6         93 $para->text->append( $line );
95 6         102 next;
96             }
97              
98 101 100       217 if( $line =~ s/^\`\`\`// ) {
99 2         11 my $language = $line =~ s/^\s+|\s+$//gr;
100 2 50       14 push @_paragraphs, App::sdview::Para::Verbatim->new(
101             language => ( length $language ? $language : undef ),
102             text => String::Tagged->new,
103             );
104 2         26 $in_verb++;
105 2         7 next;
106             }
107              
108 99 100       201 if( length $line ) {
109 59         102 push @lines, $line;
110 59         105 next;
111             }
112              
113 40         90 while( @lines ) {
114 45 50 100     504 if( $lines[0] =~ m/^