| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Mojolicious::Plugin::HTMLLint; | 
| 2 | 1 |  |  | 1 |  | 723 | use Mojo::Base 'Mojolicious::Plugin'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 3 |  |  |  |  |  |  |  | 
| 4 | 1 |  |  | 1 |  | 617 | use HTML::Lint; | 
|  | 1 |  |  |  |  | 12674 |  | 
|  | 1 |  |  |  |  | 26 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 1 |  |  | 1 |  | 23 | use v5.10; # earliest occurance of feature | 
|  | 1 |  |  |  |  | 2 |  | 
| 7 | 1 |  |  | 1 |  | 573 | no if $] >= 5.017011, warnings => 'experimental::smartmatch'; | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | our $VERSION = '0.06'; | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | sub register { | 
| 12 | 1 |  |  | 1 | 1 | 47 | my ( $self, $app, $conf ) = @_; | 
| 13 | 1 |  | 50 |  |  | 4 | $conf ||= {}; | 
| 14 |  |  |  |  |  |  |  | 
| 15 | 1 |  | 50 |  |  | 6 | my $skip = delete $conf->{skip} // []; | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | # On error callback | 
| 18 | 1 |  |  |  |  | 1 | my $on_error; | 
| 19 | 1 | 50 | 33 |  |  | 7 | if ( $conf->{on_error} && ref($conf->{on_error}) eq 'CODE' ) { | 
| 20 | 1 |  |  |  |  | 2 | $on_error = delete $conf->{on_error}; | 
| 21 |  |  |  |  |  |  | } else { | 
| 22 | 0 |  |  | 0 |  | 0 | $on_error = sub { $app->log->warn($_[1]) }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 23 |  |  |  |  |  |  | } | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | $app->hook( | 
| 26 |  |  |  |  |  |  | 'after_dispatch' => sub { | 
| 27 | 2 |  |  | 2 |  | 20486 | my ( $c ) = @_; | 
| 28 | 2 |  |  |  |  | 7 | my $res = $c->res; | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | # Only successful response | 
| 31 | 2 | 50 |  |  |  | 15 | return if $res->code !~ m/^2/; | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | ## Only html response | 
| 34 | 2 | 50 |  |  |  | 20 | return unless $res->headers->content_type; | 
| 35 | 2 | 50 |  |  |  | 26 | return if $res->headers->content_type !~ /html/; | 
| 36 |  |  |  |  |  |  |  | 
| 37 | 2 |  |  |  |  | 36 | my $lint = HTML::Lint->new(%$conf); | 
| 38 | 2 |  |  |  |  | 30 | $lint->parse($res->body); | 
| 39 | 2 |  |  |  |  | 2136 | $lint->eof(); | 
| 40 |  |  |  |  |  |  |  | 
| 41 | 2 |  |  |  |  | 96 | foreach my $error ( $lint->errors ) { | 
| 42 | 3 |  |  |  |  | 35 | my $err_msg = $error->as_string(); | 
| 43 | 3 | 50 |  |  |  | 64 | next if $err_msg ~~ $skip; | 
| 44 |  |  |  |  |  |  |  | 
| 45 | 3 |  |  |  |  | 6 | $on_error->( $c, "HTMLLint:" . $error->as_string ); | 
| 46 |  |  |  |  |  |  | } | 
| 47 | 1 |  |  |  |  | 11 | } ); | 
| 48 |  |  |  |  |  |  | } | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | 1; | 
| 51 |  |  |  |  |  |  | __END__ |