File Coverage

blib/lib/Tags/HTML/Page/Begin.pm
Criterion Covered Total %
statement 132 132 100.0
branch 58 58 100.0
condition 9 9 100.0
subroutine 11 11 100.0
pod 2 2 100.0
total 212 212 100.0


line stmt bran cond sub pod time code
1             package Tags::HTML::Page::Begin;
2              
3 4     4   160681 use strict;
  4         38  
  4         122  
4 4     4   23 use warnings;
  4         8  
  4         112  
5              
6 4     4   1050 use Class::Utils qw(set_params);
  4         27703  
  4         121  
7 4     4   146 use Error::Pure qw(err);
  4         7  
  4         159  
8 4     4   1255 use List::MoreUtils qw(none);
  4         30613  
  4         23  
9 4     4   3521 use Readonly;
  4         14  
  4         6196  
10              
11             # Constants.
12             Readonly::Hash my %LANG => (
13             'title' => 'Page title',
14             );
15              
16             our $VERSION = 0.15;
17              
18             # Constructor.
19             sub new {
20 35     35 1 95158 my ($class, @params) = @_;
21              
22             # Create object.
23 35         88 my $self = bless {}, $class;
24              
25             # Application name.
26 35         84 $self->{'application-name'} = undef;
27              
28             # Author.
29 35         58 $self->{'author'} = undef;
30              
31             # Base element.
32 35         56 $self->{'base_href'} = undef;
33 35         61 $self->{'base_target'} = undef;
34              
35             # 'CSS::Struct' object.
36 35         59 $self->{'css'} = undef;
37              
38             # Init CSS style.
39 35         137 $self->{'css_init'} = [
40             ['s', '*'],
41             ['d', 'box-sizing', 'border-box'],
42             ['d', 'margin', 0],
43             ['d', 'padding', 0],
44             ['e'],
45             ];
46              
47             # CSS links.
48 35         70 $self->{'css_src'} = [];
49              
50             # Charset.
51 35         93 $self->{'charset'} = 'UTF-8';
52              
53             # Description.
54 35         60 $self->{'description'} = undef;
55              
56             # Doctype.
57 35         66 $self->{'doctype'} = '';
58              
59             # Favicon.
60 35         60 $self->{'favicon'} = undef;
61              
62             # Generator.
63 35         214 $self->{'generator'} = 'Perl module: '.__PACKAGE__.', Version: '.$VERSION;
64              
65             # HTML element lang attribute.
66 35         67 $self->{'html_lang'} = 'en';
67              
68             # http-equiv content-type.
69 35         59 $self->{'http_equiv_content_type'} = 'text/html';
70              
71             # Keywords.
72 35         90 $self->{'keywords'} = undef;
73              
74             # Languages.
75 35         98 $self->{'lang'} = \%LANG;
76              
77             # Refresh.
78 35         57 $self->{'refresh'} = undef;
79              
80             # Robots.
81 35         57 $self->{'robots'} = undef;
82              
83             # RSS
84 35         47 $self->{'rss'} = undef;
85              
86             # Script js code.
87 35         65 $self->{'script_js'} = [];
88              
89             # Script js sources.
90 35         51 $self->{'script_js_src'} = [];
91              
92             # 'Tags' object.
93 35         57 $self->{'tags'} = undef;
94              
95             # Viewport.
96 35         58 $self->{'viewport'} = 'width=device-width, initial-scale=1.0';
97              
98             # Process params.
99 35         113 set_params($self, @params);
100              
101             # Check to 'Tags' object.
102 35 100 100     858 if (! $self->{'tags'} || ! $self->{'tags'}->isa('Tags::Output')) {
103 2         9 err "Parameter 'tags' must be a 'Tags::Output::*' class.";
104             }
105              
106             # Check to 'CSS::Struct' object.
107 33 100 100     126 if ($self->{'css'} && ! $self->{'css'}->isa('CSS::Struct::Output')) {
108 1         4 err "Parameter 'css' must be a 'CSS::Struct::Output::*' class.";
109             }
110              
111             # Check for 'css_src' array.
112 32 100       85 if (ref $self->{'css_src'} ne 'ARRAY') {
113 1         4 err "Parameter 'css_src' must be a array.";
114             }
115 31         49 foreach my $css_src_hr (@{$self->{'css_src'}}) {
  31         80  
116 4 100       17 if (ref $css_src_hr ne 'HASH') {
117 1         4 err "Parameter 'css_src' must be a array of hash structures.";
118             }
119 3         5 foreach my $key (keys %{$css_src_hr}) {
  3         11  
120 4 100   6   20 if (none { $key eq $_ } qw(link media)) {
  6         22  
121 1         5 err "Parameter 'css_src' must be a array of hash ".
122             "structures with 'media' and 'link' keys."
123             }
124             }
125             }
126              
127             # Check charset.
128 29 100       70 if (! defined $self->{'charset'}) {
129 1         5 err "Parameter 'charset' is required.";
130             }
131              
132             # Check for 'script_js' array.
133 28 100       68 if (ref $self->{'script_js'} ne 'ARRAY') {
134 2         7 err "Parameter 'script_js' must be a array.";
135             }
136              
137             # Check for 'script_js_src' array.
138 26 100       53 if (ref $self->{'script_js_src'} ne 'ARRAY') {
139 2         6 err "Parameter 'script_js_src' must be a array.";
140             }
141              
142             # Check for favicon.
143 24 100 100     93 if (defined $self->{'favicon'} && $self->{'favicon'} !~ m/\.(ico|png|jpg|gif|svg)$/ms) {
144 1         5 err "Parameter 'favicon' contain bad image type.";
145             }
146              
147             # Object.
148 23         187 return $self;
149             }
150              
151             # Process 'Tags'.
152             sub process {
153 20     20 1 294 my $self = shift;
154              
155 20         27 my $css;
156 20 100       43 if ($self->{'css'}) {
157             $self->{'css'}->put(
158 2         5 @{$self->{'css_init'}},
  2         9  
159             );
160 2         171 $css = $self->{'css'}->flush(1);
161 2 100       75 if ($css ne '') {
162 1         3 $css .= "\n";
163             } else {
164 1         2 undef $css;
165             }
166             }
167              
168             # Begin of page.
169             $self->{'tags'}->put(
170             ['r', $self->{'doctype'}],
171             ['r', "\n"],
172             ['b', 'html'],
173 20         129 ['a', 'lang', $self->{'html_lang'}],
174             ['b', 'head'],
175             );
176              
177 20 100       2734 if (defined $self->{'http_equiv_content_type'}) {
178             $self->{'tags'}->put(
179             ['b', 'meta'],
180             ['a', 'http-equiv', 'Content-Type'],
181             ['a', 'content', $self->{'http_equiv_content_type'}.
182 19         103 '; charset='.$self->{'charset'}],
183             ['e', 'meta'],
184             );
185             }
186 20 100       2175 if (defined $self->{'base_href'}) {
187             $self->{'tags'}->put(
188             ['b', 'base'],
189             ['a', 'href', $self->{'base_href'}],
190             defined $self->{'base_target'} ? (
191 2 100       23 ['a', 'target', $self->{'base_target'}],
192             ) : (),
193             ['e', 'base'],
194             );
195             }
196 20 100       242 if (! defined $self->{'http_equiv_content_type'}) {
197             $self->{'tags'}->put(
198             ['b', 'meta'],
199 1         7 ['a', 'charset', $self->{'charset'}],
200             ['e', 'meta'],
201             );
202             }
203 20         134 $self->_meta('application-name');
204 20         43 $self->_meta('author');
205 20         42 $self->_meta('description');
206 20         42 $self->_meta('generator');
207 20         49 $self->_meta('keywords');
208 20         40 $self->_meta('robots');
209 20         42 $self->_meta('viewport');
210 20 100       48 if (defined $self->{'refresh'}) {
211             $self->{'tags'}->put(
212             ['b', 'meta'],
213             ['a', 'http-equiv', 'refresh'],
214 1         8 ['a', 'content', $self->{'refresh'}],
215             ['e', 'meta'],
216             );
217             }
218              
219 20         160 $self->_favicon;
220              
221 20 100       27 if (@{$self->{'script_js'}}) {
  20         51  
222 1         3 foreach my $script_js (@{$self->{'script_js'}}) {
  1         4  
223 2         113 $self->{'tags'}->put(
224             ['b', 'script'],
225             ['a', 'type', 'text/javascript'],
226             ['d', $script_js],
227             ['e', 'script'],
228             );
229             }
230             }
231 20 100       150 if (@{$self->{'script_js_src'}}) {
  20         43  
232 1         2 foreach my $script_js_src (@{$self->{'script_js_src'}}) {
  1         3  
233 2         120 $self->{'tags'}->put(
234             ['b', 'script'],
235             ['a', 'type', 'text/javascript'],
236             ['a', 'src', $script_js_src],
237             ['e', 'script'],
238             );
239             }
240             }
241              
242             $self->{'tags'}->put(
243             defined $self->{'lang'}->{'title'} ? (
244             ['b', 'title'],
245 20 100       238 ['d', $self->{'lang'}->{'title'}],
    100          
246             ['e', 'title'],
247             ) : (),
248              
249             (
250             defined $css ? (
251             ['b', 'style'],
252             ['a', 'type', 'text/css'],
253             ['d', $css],
254             ['e', 'style'],
255             ) : (),
256             ),
257             );
258 20 100       2061 if (@{$self->{'css_src'}}) {
  20         75  
259 1         2 foreach my $css_src_hr (@{$self->{'css_src'}}) {
  1         6  
260             $self->{'tags'}->put(
261             ['b', 'link'],
262             ['a', 'rel', 'stylesheet'],
263             ['a', 'href', $css_src_hr->{'link'}],
264             $css_src_hr->{'media'} ? (
265 2 100       168 ['a', 'media', $css_src_hr->{'media'}],
266             ) : (),
267             ['a', 'type', 'text/css'],
268             ['e', 'link'],
269             );
270             }
271             }
272              
273 20 100       199 if (defined $self->{'rss'}) {
274             $self->{'tags'}->put(
275             ['b', 'link'],
276             ['a', 'rel', 'alternate'],
277             ['a', 'type', 'application/rss+xml'],
278             ['a', 'title', 'RSS'],
279 1         15 ['a', 'href', $self->{'rss'}],
280             ['e', 'link'],
281             );
282             }
283              
284 20         233 $self->{'tags'}->put(
285             ['e', 'head'],
286             ['b', 'body'],
287             );
288              
289 20         1268 return;
290             }
291              
292             sub _favicon {
293 20     20   37 my $self = shift;
294              
295 20 100       75 if (! defined $self->{'favicon'}) {
296 15         24 return;
297             }
298              
299 5         27 my ($suffix) = $self->{'favicon'} =~ m/\.(ico|png|jpg|gif|svg)$/ms;
300 5         11 my $image_type;
301 5 100       33 if ($suffix eq 'ico') {
    100          
    100          
    100          
302 1         2 $image_type = 'image/vnd.microsoft.icon';
303             } elsif ($suffix eq 'png') {
304 1         2 $image_type = 'image/png';
305             } elsif ($suffix eq 'svg') {
306 1         3 $image_type = 'image/svg+xml';
307             } elsif ($suffix eq 'gif') {
308 1         3 $image_type = 'image/gif';
309             } else {
310 1         4 $image_type = 'image/jpeg';
311             }
312              
313             $self->{'tags'}->put(
314             ['b', 'link'],
315             ['a', 'rel', 'icon'],
316 5         29 ['a', 'href', $self->{'favicon'}],
317             ['a', 'type', $image_type],
318             ['e', 'link'],
319             );
320              
321 5         723 return;
322             }
323              
324             sub _meta {
325 140     140   224 my ($self, $key) = @_;
326              
327 140 100       281 if (! defined $self->{$key}) {
328 121         172 return;
329             }
330              
331             $self->{'tags'}->put(
332             ['b', 'meta'],
333             ['a', 'name', $key],
334 19         89 ['a', 'content', $self->{$key}],
335             ['e', 'meta'],
336             );
337              
338 19         2173 return;
339             }
340              
341             1;
342              
343             __END__