File Coverage

blib/lib/HTML/MasonX/Free/Compiler.pm
Criterion Covered Total %
statement 27 75 36.0
branch 4 34 11.7
condition 8 18 44.4
subroutine 9 11 81.8
pod 4 4 100.0
total 52 142 36.6


line stmt bran cond sub pod time code
1 3     3   567973 use strict;
  3         19  
  3         116  
2 3     3   17 use warnings;
  3         11  
  3         203  
3             package HTML::MasonX::Free::Compiler;
4             {
5             $HTML::MasonX::Free::Compiler::VERSION = '0.005';
6             }
7 3     3   16 use parent 'HTML::Mason::Compiler::ToObject';
  3         4  
  3         67  
8             # ABSTRACT: an HTML::Mason compiler that can reject more input
9              
10              
11 3     3   105946 use namespace::autoclean;
  3         42436  
  3         20  
12              
13 3     3   191 use HTML::Mason::Exceptions(abbr => [qw(param_error)]);
  3         5  
  3         31  
14              
15 3     3   168 use Params::Validate qw(:all);
  3         6  
  3         929  
16             Params::Validate::validation_options(on_fail => sub {param_error join '', @_});
17              
18             BEGIN {
19 3     3   66 __PACKAGE__->valid_params(
20             allow_stray_content => {
21             parse => 'boolean',
22             type => SCALAR,
23             default => 1,
24             descr => "Whether to allow content outside blocks, or die",
25             },
26             default_method_to_call => {
27             parse => 'string',
28             type => SCALAR,
29             optional => 1,
30             descr => "A method to always call instead of calling a comp directly",
31             },
32             );
33             }
34              
35             sub text {
36 7     7 1 9172 my ($self, %arg) = @_;
37 7 100 66     48 if (
      100        
38             $self->{current_compile}{in_main}
39             and ! $self->{allow_stray_content}
40             and $arg{text} =~ /\S/
41             ) {
42 1         4 $self->lexer->throw_syntax_error(
43             "text outside of block: <<'END_TEXT'\n$arg{text}END_TEXT"
44             );
45             }
46 6         25 $self->SUPER::text(%arg);
47             }
48              
49             sub perl_line {
50 2     2 1 5139 my ($self, %arg) = @_;
51              
52 2 100 33     34 if (
      66        
53             $self->{current_compile}{in_main}
54             and ! $self->{allow_stray_content}
55             and $arg{line} !~ /\A\s*#/
56             ) {
57 1         5 $self->lexer->throw_syntax_error(
58             "perl outside of block: $arg{line}\n"
59             );
60             }
61 1         12 $self->SUPER::perl_line(%arg);
62             }
63              
64             # BEGIN DIRECT THEFT FROM HTML-Mason 1.50
65             sub component_call
66             {
67 0     0 1   my $self = shift;
68 0           my %p = @_;
69              
70 0           my ($prespace, $call, $postspace) = ($p{call} =~ /(\s*)(.*)(\s*)/s);
71 0 0         if ( $call =~ m,^[\w/.],)
72             {
73 0           my $comma = index($call, ',');
74 0 0         $comma = length $call if $comma == -1;
75 0           (my $comp = substr($call, 0, $comma)) =~ s/\s+$//;
76 0 0 0       if (defined $self->{default_method_to_call} and $comp !~ /:/) { ##
77 0           $comp = "$comp:$self->{default_method_to_call}"; ##
78             } ##
79 0           $call = "'$comp'" . substr($call, $comma);
80             }
81 0           my $code = "\$m->comp( $prespace $call $postspace \n); ";
82 0 0         eval { $self->postprocess_perl->(\$code) } if $self->postprocess_perl;
  0            
83 0 0         compiler_error $@ if $@;
84              
85 0           $self->_add_body_code($code);
86              
87 0           $self->{current_compile}{last_body_code_type} = 'component_call';
88             }
89              
90             sub component_content_call_end
91             {
92 0     0 1   my $self = shift;
93 0           my $c = $self->{current_compile};
94 0           my %p = @_;
95              
96 0           $self->lexer->throw_syntax_error("Found component with content ending tag but no beginning tag")
97 0 0         unless @{ $c->{comp_with_content_stack} };
98              
99 0           my $call = pop @{ $c->{comp_with_content_stack} };
  0            
100 0           my $call_end = $p{call_end};
101 0           for ($call_end) { s/^\s+//; s/\s+$//; }
  0            
  0            
102              
103 0           my $comp = undef;
104 0 0         if ( $call =~ m,^[\w/.],)
105             {
106 0           my $comma = index($call, ',');
107 0 0         $comma = length $call if $comma == -1;
108 0           ($comp = substr($call, 0, $comma)) =~ s/\s+$//;
109 0 0 0       if (defined $self->{default_method_to_call} and $comp !~ /:/) { ##
110 0           $comp = "$comp:$self->{default_method_to_call}"; ##
111             } ##
112 0           $call = "'$comp'" . substr($call, $comma);
113             }
114 0 0         if ($call_end) {
115 0 0         if ($call_end !~ m,^[\w/.],) {
116 0           $self->lexer->throw_syntax_error("Cannot use an expression inside component with content ending tag; use a bare component name or </&> instead");
117             }
118 0 0         if (!defined($comp)) {
119 0           $self->lexer->throw_syntax_error("Cannot match an expression as a component name; use </&> instead");
120             }
121 0 0         if ($call_end ne $comp) {
122 0           $self->lexer->throw_syntax_error("Component name in ending tag ($call_end) does not match component name in beginning tag ($comp)");
123             }
124             }
125              
126 0           my $code = "} }, $call\n );\n";
127              
128 0 0         eval { $self->postprocess_perl->(\$code) } if $self->postprocess_perl;
  0            
129 0 0         compiler_error $@ if $@;
130              
131 0           $self->_add_body_code($code);
132              
133 0           $c->{last_body_code_type} = 'component_content_call_end';
134             }
135             # END DIRECT THEFT FROM HTML-Mason 1.50
136              
137             1;
138              
139             __END__
140              
141             =pod
142              
143             =head1 NAME
144              
145             HTML::MasonX::Free::Compiler - an HTML::Mason compiler that can reject more input
146              
147             =head1 VERSION
148              
149             version 0.005
150              
151             =head1 OVERVIEW
152              
153             This is an alternate compiler for HTML::Mason. It's meant to fill in for the
154             default, L<HTML::Mason::Compiler::ToObject>. (Don't trust things telling you
155             that the default is HTML::Mason::Compiler. If you're using Mason, you're
156             almost certainly have ToObject doing the work.)
157              
158             By default, it I<should> behave just like the normal compiler, but more options
159             can be provided to make it stricter.
160              
161             Right now, there's just one extra option, but there will be more.
162              
163             =head1 ATTRIBUTES
164              
165             =head2 allow_stray_content
166              
167             If false, any text outside of a block (like a method or doc block), other than
168             blank lines, will be fatal. Similar, any Perl lines other than comments will
169             be fatal.
170              
171             =head2 default_method_to_call
172              
173             If set, this is the name of a method that will be dropped in place whenever the
174             user is trying to call a component without a method. For example, if you set
175             it to "main" then this:
176              
177             <& /foo/bar &>
178              
179             ...will be treated like this:
180              
181             <& /foo/bar:main &>
182              
183             To keep this consistent with the top-level called performed by the mason
184             interpreter, you should probably also use L<HTML::MasonX::Free::Component> as
185             your component class.
186              
187             =head1 AUTHOR
188              
189             Ricardo Signes <rjbs@cpan.org>
190              
191             =head1 COPYRIGHT AND LICENSE
192              
193             This software is copyright (c) 2013 by Ricardo Signes.
194              
195             This is free software; you can redistribute it and/or modify it under
196             the same terms as the Perl 5 programming language system itself.
197              
198             =cut