File Coverage

blib/lib/Markapl/TagHandlers.pm
Criterion Covered Total %
statement 115 123 93.5
branch 30 36 83.3
condition 8 14 57.1
subroutine 19 21 90.4
pod 0 11 0.0
total 172 205 83.9


line stmt bran cond sub pod time code
1             package Markapl::TagHandlers;
2              
3 22     22   171 use strict;
  22         281  
  22         726  
4 22     22   315 use warnings;
  22         153  
  22         635  
5 22     22   112 use Devel::Declare ();
  22         33  
  22         395  
6 22     22   22414 use B::Hooks::EndOfScope;
  22         550581  
  22         205  
7 22     22   28526 use HTML::Entities;
  22         192831  
  22         27019  
8              
9             our $VERSION = 0.03;
10              
11             our ($Declarator, $Offset);
12              
13             sub skip_declarator {
14 227     227 0 546 $Offset += Devel::Declare::toke_move_past_token($Offset);
15             }
16              
17             sub skipspace {
18 1135     1135 0 2183 $Offset += Devel::Declare::toke_skipspace($Offset);
19             }
20              
21             sub strip_name {
22 227     227 0 356 skipspace;
23 227 50       738 if (my $len = Devel::Declare::toke_scan_word($Offset, 1)) {
24 0         0 my $linestr = Devel::Declare::get_linestr();
25 0         0 my $name = substr($linestr, $Offset, $len);
26 0         0 substr($linestr, $Offset, $len) = '';
27 0         0 Devel::Declare::set_linestr($linestr);
28 0         0 return $name;
29             }
30 227         360 return;
31             }
32              
33             sub strip_proto {
34 227     227 0 333 skipspace;
35              
36 227         525 my $linestr = Devel::Declare::get_linestr();
37 227 100       593 if (substr($linestr, $Offset, 1) eq '(') {
38 60         383 my $length = Devel::Declare::toke_scan_str($Offset);
39 60         210 my $proto = Devel::Declare::get_lex_stuff();
40 60         105 Devel::Declare::clear_lex_stuff();
41 60         131 $linestr = Devel::Declare::get_linestr();
42 60         103 substr($linestr, $Offset, $length) = '';
43 60         107 Devel::Declare::set_linestr($linestr);
44 60         130 return $proto;
45             }
46 167         298 return;
47             }
48              
49             sub shadow {
50 227     227 0 475 my $pack = Devel::Declare::get_curstash_name;
51 227         883 Devel::Declare::shadow_sub("${pack}::${Declarator}", $_[0]);
52             }
53              
54             sub make_proto_unwrap {
55 0     0 0 0 my ($proto) = @_;
56 0 0 0     0 return (defined($proto) && length($proto)) ? "($proto);" : "";
57             }
58              
59             sub inject_if_block {
60 227     227 0 334 my $inject = shift;
61 227         370 skipspace;
62 227         451 my $linestr = Devel::Declare::get_linestr;
63 227 100       577 if (substr($linestr, $Offset, 1) eq '{') {
64 211         363 substr($linestr, $Offset+1, 0) = $inject;
65 211         614 Devel::Declare::set_linestr($linestr);
66             }
67             }
68              
69             sub inject_before_block {
70 227     227 0 263 my $inject = shift;
71 227         404 skipspace;
72 227         462 my $linestr = Devel::Declare::get_linestr;
73 227 50       626 if (substr($linestr, $Offset, 1) eq '{') {
74 227         332 substr($linestr, $Offset, 0) = $inject;
75 227         513 Devel::Declare::set_linestr($linestr);
76             }
77             }
78              
79             sub inject_empty_block {
80 227     227 0 264 my $inject = "{}";
81 227         324 skipspace;
82 227         479 my $linestr = Devel::Declare::get_linestr;
83 227 100       608 if (substr($linestr, $Offset, 1) eq ';') {
84 16         30 substr($linestr, $Offset, 0) = $inject;
85 16         46 Devel::Declare::set_linestr($linestr);
86             }
87             }
88              
89             sub inject_scope {
90             on_scope_end {
91 211     211   5771 my $linestr = Devel::Declare::get_linestr;
92 211         429 my $offset = Devel::Declare::get_linestr_offset;
93 211         371 substr($linestr, $offset, 0) = ';';
94 211         630 Devel::Declare::set_linestr($linestr);
95 211     211 0 16404 };
96             }
97              
98             my %alt = (
99             'cell' => 'td',
100             'row' => 'tr',
101             'html_base' => 'base',
102             'html_link' => 'link',
103             'html_map' => 'map',
104             'html_q' => 'q',
105             'html_s' => 's',
106             'html_sub' => 'sub',
107             'html_tr' => 'tr',
108             );
109              
110 22     22   22018 use String::BufferStack;
  22         43803  
  22         20203  
111              
112             sub _tag {
113 109     109   230 my ($tag, $attr, $block, $in_closure) = @_;
114              
115 109         130 my $original_buffer;
116              
117 109 100       307 if ($in_closure) {
118 2         15 $original_buffer = Markapl->buffer;
119 2     0   14 Markapl->buffer( String::BufferStack->new( out_method => sub { join("", @_) }) );
  0         0  
120 2         8 Markapl->buffer->push;
121             }
122              
123 109 100       577 if (grep { $tag eq $_ } Markapl::Tags->html_inline) {
  1853         2812  
124 9         31 Markapl->buffer->append("<${tag}${attr}>");
125             }
126             else {
127 100         310 Markapl->buffer->append("<${tag}${attr}>");
128 101 100 66     1014 Markapl->buffer->append(
      100        
129             join '', map {
130 100 50 33     1905 ref($_) && $_->isa('Markapl::Tag') ? $_->() : ($_||"")
131             } $block->()
132             ) if defined $block && ref($block) eq 'CODE';
133 100         1370 Markapl->buffer->append("");
134             }
135              
136 109 100       1496 if ($original_buffer) {
137 2         7 my $output = Markapl->buffer->pop;
138 2         64 Markapl->buffer($original_buffer);
139 2         9 return $output;
140             }
141              
142 107         190 return '';
143             }
144              
145             sub tag_parser_for {
146 2726     2726 0 3390 my ($tag) = @_;
147 2726 100       6570 $tag = $alt{$tag} if defined($alt{$tag});
148              
149             return sub {
150 227     227   29427 local ($Declarator, $Offset) = @_;
151              
152 227         344 my $offset_before = $Offset;
153 227         418 skip_declarator;
154              
155             # This means that current declarator is in a hash key.
156             # Don't shadow sub in this case
157 227 50       508 return if $Offset == $offset_before;
158              
159 227         414 my $name = strip_name;
160 227         430 my $proto = strip_proto;
161              
162 227         659 inject_if_block("BEGIN { Markapl::TagHandlers::inject_scope };");
163 227         346 inject_empty_block;
164              
165 227 100       408 if (defined($proto)) {
166 60         156 inject_before_block("$proto, sub");
167             }
168             else {
169 167         277 inject_before_block("sub");
170             }
171              
172             shadow(
173             sub {
174 109         757 my $block = pop;
175 109         230 my @attr = @_;
176              
177 109         183 my $attr = "";
178              
179 109 100       267 if (@attr == 1) {
180 4         9 my $css = $attr[0];
181 4         56 while ($css =~ /([\#\.])([A-Za-z][-:\.\w]*)/g) {
182 4 100       27 if ($1 eq '#') {
183 1         6 $attr .= qq{ id="$2"};
184             } else {
185 3         26 $attr .= qq{ class="$2"};
186             }
187             }
188             } else {
189 105         214 my ($k, $v) = (shift @attr, shift @attr);
190 105         301 while ($k) {
191 25 100       74 if (defined $v) {
192 24         98 $v = encode_entities($v, '<>&"');
193 24         2943 $attr .= " $k=\"$v\"";
194             } else {
195 1         2 $attr .= " $k";
196             }
197              
198 25         104 ($k, $v) = (shift @attr, shift @attr);
199             }
200             }
201              
202 109 100 100     392 if (defined wantarray and not wantarray) {
203             my $sub = sub {
204 2         10 _tag($tag, $attr, $block, 1);
205 2         11 };
206 2         10 bless $sub, 'Markapl::Tag';
207 2         7 return $sub;
208             }
209 107         404 _tag($tag, $attr, $block);
210 107         325 return '';
211             }
212 227         1642 );
213              
214             }
215 2726         35931 }
216              
217             1;