File Coverage

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


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