blib/lib/Swim/HTML.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 17 | 142 | 11.9 |
branch | 1 | 48 | 2.0 |
condition | 0 | 3 | 0.0 |
subroutine | 5 | 29 | 17.2 |
pod | 0 | 26 | 0.0 |
total | 23 | 248 | 9.2 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package Swim::HTML; | ||||||
2 | 2 | 2 | 760 | use Pegex::Base; | |||
2 | 3 | ||||||
2 | 9 | ||||||
3 | extends 'Swim::Markup'; | ||||||
4 | |||||||
5 | 2 | 2 | 2959 | use HTML::Escape; | |||
2 | 2154 | ||||||
2 | 98 | ||||||
6 | |||||||
7 | 2 | 2 | 10 | use constant top_block_separator => "\n"; | |||
2 | 4 | ||||||
2 | 3952 | ||||||
8 | |||||||
9 | my $document_title = ''; | ||||||
10 | my $info = { | ||||||
11 | verse => { | ||||||
12 | tag => 'p', | ||||||
13 | style => 'block', | ||||||
14 | transform => 'transform_verse', | ||||||
15 | attrs => ' class="verse"', | ||||||
16 | }, | ||||||
17 | }; | ||||||
18 | |||||||
19 | sub render_text { | ||||||
20 | 1 | 1 | 0 | 2 | my ($self, $text) = @_; | ||
21 | 1 | 2 | $text =~ s/\n/ /g; | ||||
22 | 1 | 6 | escape_html($text); | ||||
23 | } | ||||||
24 | |||||||
25 | sub render_para { | ||||||
26 | 1 | 1 | 0 | 3 | my ($self, $node) = @_; | ||
27 | 1 | 3 | my $out = $self->render($node); | ||||
28 | 1 | 3 | chomp $out; | ||||
29 | 1 | 50 | 4 | my $spacer = $out =~ /\n/ ? "\n" : ''; | |||
30 | 1 | 4 | " $spacer$out$spacer \n"; |
||||
31 | } | ||||||
32 | |||||||
33 | sub render_rule { | ||||||
34 | 0 | 0 | 0 | " \n"; |
|||
35 | } | ||||||
36 | |||||||
37 | sub render_blank { | ||||||
38 | 0 | 0 | 0 | " \n"; |
|||
39 | } | ||||||
40 | |||||||
41 | sub render_list { | ||||||
42 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
43 | 0 | my $out = $self->render($node); | |||||
44 | 0 | chomp $out; | |||||
45 | 0 | "
|
|||||
46 | } | ||||||
47 | |||||||
48 | sub render_item { | ||||||
49 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
50 | 0 | my $out = $self->render($node); | |||||
51 | 0 | $out =~ s/(.)(<(?:ul|pre|p)(?: |>))/$1\n$2/; | |||||
52 | 0 | 0 | my $spacer = $out =~ /\n/ ? "\n" : ''; | ||||
53 | 0 | " |
|||||
54 | } | ||||||
55 | |||||||
56 | sub render_olist { | ||||||
57 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
58 | 0 | my $out = $self->render($node); | |||||
59 | 0 | chomp $out; | |||||
60 | 0 | "
|
|||||
61 | } | ||||||
62 | |||||||
63 | sub render_oitem { | ||||||
64 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
65 | 0 | $self->render_item($node); | |||||
66 | } | ||||||
67 | |||||||
68 | sub render_data { | ||||||
69 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
70 | 0 | my $out = "
|
|||||
71 | 0 | for my $item (@$node) { | |||||
72 | 0 | my ($term, $def, $rest) = @$item; | |||||
73 | 0 | $term = $self->render($term); | |||||
74 | 0 | $out .= " |
|||||
75 | 0 | 0 | 0 | if (length $def or $rest) { | |||
76 | 0 | $out .= " |
|||||
77 | 0 | 0 | if (length $def) { | ||||
78 | 0 | $out .= $self->render($def) . "\n"; | |||||
79 | } | ||||||
80 | 0 | 0 | if ($rest) { | ||||
81 | 0 | $out .= $self->render($rest) . "\n"; | |||||
82 | } | ||||||
83 | 0 | $out .= " |
|||||
84 | } | ||||||
85 | } | ||||||
86 | 0 | $out . "\n"; | |||||
87 | } | ||||||
88 | |||||||
89 | sub render_pref { | ||||||
90 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
91 | 0 | my $out = escape_html($node); | |||||
92 | 0 | " \n"; |
|||||
93 | } | ||||||
94 | |||||||
95 | sub render_pfunc { | ||||||
96 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
97 | 0 | 0 | if ($node =~ /^(\w[\-\w]*) ?((?s:.*)?)$/) { | ||||
98 | 0 | my ($name, $args) = ($1, $2); | |||||
99 | 0 | $name =~ s/-/_/g; | |||||
100 | 0 | my $method = "phrase_func_$name"; | |||||
101 | 0 | 0 | if ($self->can($method)) { | ||||
102 | 0 | my $out = $self->$method($args); | |||||
103 | 0 | 0 | return $out if defined $out; | ||||
104 | } | ||||||
105 | } | ||||||
106 | 0 | "<$node>"; | |||||
107 | } | ||||||
108 | |||||||
109 | sub render_title { | ||||||
110 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
111 | 0 | 0 | my ($name, $abstract) = ref $node ? @$node : (undef, $node); | ||||
112 | |||||||
113 | 0 | $name = $self->render($name); | |||||
114 | 0 | 0 | if (defined $abstract) { | ||||
115 | 0 | $abstract = $self->render($abstract); | |||||
116 | 0 | $document_title = "$name - $abstract"; | |||||
117 | 0 | "$name\n\n$abstract \n"; |
|||||
118 | } | ||||||
119 | else { | ||||||
120 | 0 | $document_title = "$name"; | |||||
121 | 0 | 0 | my $spacer = $name =~ /\n/ ? "\n" : ''; | ||||
122 | 0 | "$spacer$name$spacer\n"; |
|||||
123 | } | ||||||
124 | } | ||||||
125 | |||||||
126 | sub render_head { | ||||||
127 | 0 | 0 | 0 | my ($self, $node, $number) = @_; | |||
128 | 0 | my $out = $self->render($node); | |||||
129 | 0 | chomp $out; | |||||
130 | 0 | " |
|||||
131 | } | ||||||
132 | |||||||
133 | sub render_comment { | ||||||
134 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
135 | 0 | my $out = escape_html($node); | |||||
136 | 0 | 0 | if ($out =~ /\n/) { | ||||
137 | 0 | "\n"; | |||||
138 | } | ||||||
139 | else { | ||||||
140 | 0 | "\n"; | |||||
141 | } | ||||||
142 | } | ||||||
143 | |||||||
144 | sub render_code { | ||||||
145 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
146 | 0 | my $out = $self->render($node); | |||||
147 | 0 | "$out "; |
|||||
148 | } | ||||||
149 | |||||||
150 | sub render_bold { | ||||||
151 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
152 | 0 | my $out = $self->render($node); | |||||
153 | 0 | "$out"; | |||||
154 | } | ||||||
155 | |||||||
156 | sub render_emph { | ||||||
157 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
158 | 0 | my $out = $self->render($node); | |||||
159 | 0 | "$out"; | |||||
160 | } | ||||||
161 | |||||||
162 | sub render_del { | ||||||
163 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
164 | 0 | my $out = $self->render($node); | |||||
165 | 0 | " |
|||||
166 | } | ||||||
167 | |||||||
168 | sub render_under { | ||||||
169 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
170 | 0 | my $out = $self->render($node); | |||||
171 | 0 | "$out"; | |||||
172 | } | ||||||
173 | |||||||
174 | sub render_hyper { | ||||||
175 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
176 | 0 | my ($link, $text) = @{$node}{qw(link text)}; | |||||
0 | |||||||
177 | 0 | 0 | $text = $link if not length $text; | ||||
178 | 0 | "$text"; | |||||
179 | } | ||||||
180 | |||||||
181 | sub render_link { | ||||||
182 | 0 | 0 | 0 | my ($self, $node) = @_; | |||
183 | 0 | my ($link, $text) = @{$node}{qw(link text)}; | |||||
0 | |||||||
184 | 0 | 0 | $text = $link if not length $text; | ||||
185 | |||||||
186 | # XXX Temporary hack for inline grant blog | ||||||
187 | # We can solve this in a formal and extensible way later. | ||||||
188 | 0 | 0 | if (defined $ENV{SWIM_LINK_FORMAT_HACK}) { | ||||
189 | 0 | $link = "https://metacpan.org/pod/$link"; | |||||
190 | } | ||||||
191 | |||||||
192 | 0 | "$text"; | |||||
193 | } | ||||||
194 | |||||||
195 | sub render_complete { | ||||||
196 | 0 | 0 | 0 | my ($self, $out) = @_; | |||
197 | 0 | chomp $out; | |||||
198 | <<"..." | ||||||
199 | |||||||
200 | |||||||
201 | |||||||
202 | |||||||
203 | |
||||||
204 | |||||||
205 | |||||||
206 | |||||||
207 | |
||||||
208 | |||||||
209 | $out | ||||||
210 | |||||||
211 | |||||||
212 | |||||||
213 | |||||||
214 | ... | ||||||
215 | 0 | } | |||||
216 | |||||||
217 | #------------------------------------------------------------------------------ | ||||||
218 | sub format_phrase_func_html { | ||||||
219 | 0 | 0 | 0 | my ($self, $tag, $class, $attrib, $content) = @_; | |||
220 | 0 | my $attribs = ''; | |||||
221 | 0 | 0 | if (@$class) { | ||||
222 | 0 | $attribs = ' class="' . join(' ', @$class) . '"'; | |||||
223 | } | ||||||
224 | 0 | 0 | if (@$attrib) { | ||||
225 | $attribs = ' ' . join(' ', map { | ||||||
226 | 0 | 0 | /=".*"$/ ? $_ : do { s/=(.*)/="$1"/; $_ } | ||||
0 | |||||||
0 | |||||||
0 | |||||||
227 | } @$attrib); | ||||||
228 | } | ||||||
229 | 0 | 0 | length($content) | ||||
230 | ? "<$tag$attribs>$content$tag>" | ||||||
231 | : "<$tag$attribs/>"; | ||||||
232 | } | ||||||
233 | |||||||
234 | sub phrase_func_bold { | ||||||
235 | 0 | 0 | 0 | my ($self, $args) = @_; | |||
236 | 0 | my ($success, $class, $attrib, $content) = | |||||
237 | $self->parse_phrase_func_args_html($args); | ||||||
238 | 0 | 0 | return unless $success; | ||||
239 | 0 | $self->format_phrase_func_html('strong', $class, $attrib, $content); | |||||
240 | } | ||||||
241 | |||||||
242 | sub parse_phrase_func_args_html { | ||||||
243 | 0 | 0 | 0 | my ($self, $args) = @_; | |||
244 | 0 | my ($class, $attrib, $content) = ([], [], ''); | |||||
245 | 0 | $args =~ s/^ //; | |||||
246 | 0 | 0 | if ($args =~ /\A((?:\\:|[^\:])*):((?s:.*))\z/) { | ||||
247 | 0 | $attrib = $1; | |||||
248 | 0 | $content = $2; | |||||
249 | 0 | $attrib =~ s/\\:/:/g; | |||||
250 | 0 | ($class, $attrib) = $self->parse_attrib($attrib); | |||||
251 | } | ||||||
252 | else { | ||||||
253 | 0 | $content = $args; | |||||
254 | } | ||||||
255 | 0 | return 1, $class, $attrib, $content; | |||||
256 | } | ||||||
257 | |||||||
258 | sub parse_attrib { | ||||||
259 | 0 | 0 | 0 | my ($self, $text) = @_; | |||
260 | 0 | my ($class, $attrib) = ([], []); | |||||
261 | 0 | while (length $text) { | |||||
262 | 0 | 0 | if ($text =~ s/^\s*(\w[\w\-]*)(?=\s|\z)\s*//) { | ||||
0 | |||||||
0 | |||||||
263 | 0 | push @$class, $1; | |||||
264 | } | ||||||
265 | elsif ($text =~ s/^\s*(\w[\w\-]*="[^"]*")(?=\s|\z)s*//) { | ||||||
266 | 0 | push @$attrib, $1; | |||||
267 | } | ||||||
268 | elsif ($text =~ s/^\s*(\w[\w\-]*=\S+)(?=\s|\z)s*//) { | ||||||
269 | 0 | push @$attrib, $1; | |||||
270 | } | ||||||
271 | else { | ||||||
272 | 0 | last; | |||||
273 | } | ||||||
274 | } | ||||||
275 | 0 | return $class, $attrib; | |||||
276 | } | ||||||
277 | |||||||
278 | 1; |