Commit | Line | Data |
0f9bcf09 |
1 | package Catalyst::View::TT::XHTML; |
2 | use strict; |
3 | use warnings; |
06cf3efb |
4 | use HTTP::Negotiate qw(choose); |
d58e822e |
5 | use MRO::Compat; |
0f9bcf09 |
6 | use base qw/Catalyst::View::TT/; |
7 | |
b612c798 |
8 | our $VERSION = '1.004'; |
06cf3efb |
9 | |
10 | our $variants = [ |
11 | [qw| xhtml 1.000 application/xhtml+xml |], |
56f18daf |
12 | [qw| html 0.900 text/html |], |
06cf3efb |
13 | ]; |
0f9bcf09 |
14 | |
15 | sub process { |
16 | my $self = shift; |
17 | my ($c) = @_; |
06cf3efb |
18 | my $return = $self->next::method(@_); |
06cf3efb |
19 | if ($c->request->header('Accept') && $c->response->headers->{'content-type'} =~ m|text/html|) { |
56f18daf |
20 | $self->pragmatic_accept($c); |
06cf3efb |
21 | my $var = choose($variants, $c->request->headers); |
22 | if ($var eq 'xhtml') { |
23 | $c->response->headers->{'content-type'} =~ s|text/html|application/xhtml+xml|; |
24 | } |
0f9bcf09 |
25 | } |
06cf3efb |
26 | return $return; |
0f9bcf09 |
27 | } |
28 | |
56f18daf |
29 | sub pragmatic_accept { |
30 | my ($self, $c) = @_; |
31 | my $accept = $c->request->header('Accept'); |
32 | if ($accept =~ m|text/html|) { |
33 | $accept =~ s!\*/\*\s*([,]+|$)!*/*;q=0.5$1!; |
34 | } else { |
35 | $accept =~ s!\*/\*\s*([,]+|$)!text/html,*/*;q=0.5$1!; |
36 | } |
37 | $c->request->header('Accept' => $accept); |
38 | } |
39 | |
0f9bcf09 |
40 | 1; |
41 | |
42 | __END__ |
43 | |
44 | =head1 NAME |
45 | |
46 | Catalyst::View::TT::XHTML - A sub-class of the standard TT view which |
47 | serves application/xhtml+xml content if the browser accepts it. |
48 | |
49 | =head1 SYNOPSIS |
50 | |
51 | package MyApp::View::XHTML; |
52 | use strict; |
53 | use warnings; |
54 | use base qw/Catalyst::View::TT::XHTML MyApp::View::TT/; |
56f18daf |
55 | |
0f9bcf09 |
56 | 1; |
56f18daf |
57 | |
0f9bcf09 |
58 | =head1 DESCRIPTION |
59 | |
60 | This is a very simple sub-class of L<Catalyst::View::TT>, which sets |
61 | the response C<Content-Type> to be C<application/xhtml+xml> if the |
62 | user's browser sends an C<Accept> header indicating that it is willing |
63 | to process that MIME type. |
64 | |
65 | Changing the C<Content-Type> causes browsers to interpret the page as |
56f18daf |
66 | XML, meaning that the markup must be well formed. |
0f9bcf09 |
67 | |
68 | This is useful when you're developing your application, as you know that |
56f18daf |
69 | all pages you view are parsed as XML, so any errors caused by your markup |
70 | not being well-formed will show up at once. |
0f9bcf09 |
71 | |
72 | =head1 METHODS |
73 | |
74 | =head2 process |
75 | |
76 | Overrides the standard process method, delegating to L<Catalyst::View::TT> |
77 | to render the template, and then changing the response C<Content-Type> if |
78 | appropriate (from the requests C<Accept> header). |
79 | |
56f18daf |
80 | =head2 pragmatic_accept |
81 | |
82 | Some browsers (such as Internet Explorer) have a nasty way of sending |
83 | Accept */* and this claiming to support XHTML just as well as HTML. |
84 | Saving to a file on disk or opening with another application does |
85 | count as accepting, but it really should have a lower q value then |
86 | text/html. This sub takes a pragmatic approach and corrects this mistake |
87 | by modifying the Accept header before passing it to content negotiation. |
88 | |
0f9bcf09 |
89 | =head1 BUGS |
90 | |
91 | There should be a more elegant way to inherit the config of your normal |
92 | TT view. |
93 | |
94 | Configuration (as loaded by L<Catalyst::Plugin::ConfigLoader>) for the TT |
95 | view is not used. |
96 | |
97 | No helper to generate the view file needed (just copy the code in the |
98 | SYNOPSIS). |
99 | |
100 | =head1 AUTHOR |
101 | |
102 | Tomas Doran C<< <bobtfish@bobtfish.net> >> |
103 | |
c2ec1d6a |
104 | =head1 CONTRIBUTORS |
105 | |
106 | =over |
107 | |
56f18daf |
108 | =item David Dorward - test patches and */* pragmatism. |
c2ec1d6a |
109 | |
110 | =back |
111 | |
0f9bcf09 |
112 | =head1 COPYRIGHT |
113 | |
114 | This module itself is copyright (c) 2008 Tomas Doran and is licensed under the same terms as Perl itself. |
115 | |
116 | =cut |