File Coverage

blib/lib/Swim/Markup.pm
Criterion Covered Total %
statement 39 70 55.7
branch 8 30 26.6
condition 1 2 50.0
subroutine 9 13 69.2
pod 1 9 11.1
total 58 124 46.7


line stmt bran cond sub pod time code
1             package Swim::Markup;
2 2     2   1475 use Pegex::Base;
  2         2  
  2         9  
3             extends 'Swim::Tree';
4              
5             has option => {};
6              
7             sub BUILD {
8 1   50 1 0 91 $_[0]->{option} ||= {};
9             }
10              
11             sub final {
12 1     1 1 618 my ($self, $tree) = @_;
13 1         2 $self->{stack} = [];
14 1         1 $self->{bullet} = [];
15 1         3 my $out = $self->render($tree);
16 1 50       14 if ($self->option->{'complete'}) {
17 0 0       0 if ($self->can('render_complete')) {
18 0         0 $out = $self->render_complete($out);
19             }
20             }
21 1         9 $out;
22             }
23              
24             sub render {
25 4     4 0 7 my ($self, $node) = @_;
26 4         4 my $out;
27 4 100       9 if (not ref $node) {
    100          
28 1         3 $out = $self->render_text($node);
29             }
30             elsif (ref($node) eq 'HASH') {
31 1         3 $out = $self->render_node($node);
32             }
33             else {
34 2         4 my $separator = $self->get_separator($node);
35 2         4 $out = join $separator, grep $_, map { $self->render($_) } @$node;
  2         11  
36             }
37 4         10 return $out;
38             }
39              
40             sub render_node {
41 1     1 0 2 my ($self, $hash) = @_;
42 1         2 my ($name, $node) = each %$hash;
43 1 50       4 my $number = $name =~ s/(\d)$// ? $1 : 0;
44 1         2 my $method = "render_$name";
45 1         1 push @{$self->{stack}}, $name;
  1         5  
46 1         3 my $out = $self->$method($node, $number);
47 1         2 pop @{$self->{stack}};
  1         1  
48 1         2 $out;
49             }
50              
51             sub render_pfunc {
52 0     0 0 0 my ($self, $node) = @_;
53 0 0       0 if ($node =~ /^([\-\w]+)(?:[\ \:]|\z)((?s:.*)?)$/) {
54 0         0 my ($name, $args) = ($1, $2);
55 0         0 my $out = $self->_render_func(phrase => $name, $args);
56 0 0       0 return $out if defined $out;
57             }
58 0         0 return "<$node>";
59             }
60              
61             sub render_bfunc {
62 0     0 0 0 my ($self, $content) = @_;
63 0         0 my ($name, $args) = @$content;
64 0 0       0 $args = '' unless defined $args;
65 0         0 my $out = $self->_render_func(block => $name, $args);
66 0 0       0 return $out if defined $out;
67 0 0       0 if ($args) {
68 0         0 chomp $args;
69 0         0 return "<<<$name\n$args\n>>>\n";
70             }
71             else {
72 0         0 return "<<<$name>>>\n";
73             }
74             }
75              
76             sub _render_func {
77 0     0   0 my ($self, $type, $name, $args) = @_;
78 0         0 (my $method = "${type}_func_$name") =~ s/-/_/g;
79 0         0 (my $plugin = "Swim::Plugin::$name") =~ s/-/::/g;
80 0         0 while (1) {
81 0 0       0 if ($self->can($method)) {
82 0         0 my $out = $self->$method($args);
83 0 0       0 return $out if defined $out;
84             }
85 0 0       0 last if $plugin eq "Swim::Plugin";
86 0         0 eval "require $plugin";
87 0         0 $plugin =~ s/(.*)::.*/$1/;
88             }
89 0         0 return;
90             }
91              
92             my $phrase_types = {
93             map { ($_, 1) } qw(
94             code
95             bold
96             emph
97             del
98             under
99             hyper
100             link
101             pfunc
102             text
103             ) };
104              
105             #------------------------------------------------------------------------------
106             # Separator controls
107             #------------------------------------------------------------------------------
108 2     2   3438 use constant default_separator => '';
  2         4  
  2         114  
109 2     2   12 use constant top_block_separator => '';
  2         24  
  2         298  
110              
111             sub get_separator {
112 2     2 0 3 my ($self, $node) = @_;
113 2 100       4 $self->at_top_level ? $self->top_block_separator : $self->default_separator;
114             }
115              
116             sub at_top_level {
117 2     2 0 2 @{$_[0]->{stack}} == 0
  2         15  
118             }
119              
120             sub node_is_block {
121 0     0 0   my ($self, $node) = @_;
122 0           my ($type) = keys %$node;
123 0 0         return($phrase_types->{$type} ? 0 : 1);
124             }
125              
126             1;