Commit | Line | Data |
ed99cbb4 |
1 | package HTML::String::TT; |
2 | |
3 | use strictures 1; |
51eaef0b |
4 | |
586054e0 |
5 | BEGIN { |
6 | if ($INC{"Template.pm"} and !$INC{"UNIVERSAL/ref.pm"}) { |
7 | warn "Template was loaded before we could load UNIVERSAL::ref" |
8 | ." - this means you're probably going to get weird errors." |
9 | ." To avoid this, use HTML::String::TT before loading Template." |
10 | } |
11 | require UNIVERSAL::ref; |
12 | } |
13 | |
51eaef0b |
14 | use HTML::String; |
15 | use HTML::String::TT::Directive; |
16 | use Safe::Isa; |
ed99cbb4 |
17 | use Template; |
18 | use Template::Parser; |
19 | use Template::Stash; |
ed99cbb4 |
20 | |
4f4204a3 |
21 | BEGIN { |
22 | my $orig_blessed = Template::Stash->can('blessed'); |
23 | no warnings 'redefine'; |
24 | *Template::Stash::blessed = sub ($) { |
25 | my $val = $orig_blessed->($_[0]); |
26 | return undef if defined($val) and $val eq 'HTML::String::Value'; |
27 | return $val; |
28 | }; |
29 | } |
30 | |
ed99cbb4 |
31 | sub new { |
32 | shift; |
33 | Template->new( |
34 | PARSER => Template::Parser->new( |
35 | FACTORY => 'HTML::String::TT::Directive' |
36 | ), |
37 | STASH => Template::Stash->new, |
51eaef0b |
38 | FILTERS => { no_escape => sub { |
39 | $_[0]->$_isa('HTML::String::Value') |
40 | ? HTML::String::Value->new(map $_->[0], @{$_[0]->{parts}}) |
41 | : HTML::String::Value->new($_) |
42 | } }, |
77724961 |
43 | (ref($_[0]) eq 'HASH' ? %{$_[0]} : @_) |
ed99cbb4 |
44 | ); |
45 | } |
46 | |
47 | 1; |
d86bdf82 |
48 | |
49 | __END__ |
50 | |
51 | =head1 NAME |
52 | |
53 | HTML::String::TT - HTML string auto-escaping for L<Template Toolkit|Template> |
54 | |
55 | =head1 SYNOPSIS |
56 | |
57 | my $tt = HTML::String::TT->new(\%normal_tt_args); |
58 | |
59 | or, if you're using L<Catalyst::View::TT>: |
60 | |
61 | use HTML::String::TT; # needs to be loaded before TT to work |
62 | |
63 | __PACKAGE__->config( |
64 | CLASS => 'HTML::String::TT', |
65 | ); |
66 | |
67 | Then, in your template - |
68 | |
69 | <h1> |
70 | [% title %] <-- this will be automatically escaped |
71 | </h1> |
72 | <div id="main"> |
73 | [% some_html | no_escape %] <-- this won't |
74 | </div> |
75 | [% html_var = '<foo>'; html_var %] <-- this won't anyway |
76 | |
77 | (but note that the C<content> key in wrappers shouldn't need this). |
78 | |
79 | =head1 DESCRIPTION |
80 | |
81 | L<HTML::String::TT> is a wrapper for L<Template Toolkit|Template> that |
82 | installs the following overrides: |
83 | |
84 | =over 4 |
85 | |
86 | =item * The directive generator is replaced with |
87 | L<HTML::String::TT::Directive> which ensures L<HTML::String::Overload> is |
88 | active for the template text. |
89 | |
90 | =item * The stash is forced to be L<Template::Stash> since |
91 | L<Template::Stash::XS> gets utterly confused if you hand it an object. |
92 | |
93 | =item * A filter C<no_escape> is added to mark outside data that you don't |
94 | want to be escaped. |
95 | |
96 | =back |
97 | |
98 | The override happens to B<all> of the plain strings in your template, so |
99 | even things declared within directives such as |
100 | |
101 | [% html_var = '<h1>' %] |
102 | |
103 | will not be escaped, but any string coming from anywhere else will be. This |
104 | can be a little bit annoying when you then pass it to things that don't |
105 | respond well to overloaded objects, but is essential to L<HTML::String>'s |
106 | policy of "always fail closed" - I'd rather it throws an exception than |
107 | lets a value through unescaped, and if you care about your HTML not having |
108 | XSS (cross site scripting) vulnerabilities then I hope you'll agree. |
109 | |
110 | We mark a number of TT internals namespaces as "don't escape when called by |
111 | these", since TT has a tendency to do things like |
112 | |
113 | open FH, "< $name"; |
114 | |
115 | which really don't work if it gets converted to C<" $name> while you |
116 | aren't looking. |
117 | |
118 | Additionally, since TT often calls C<ref> to decide e.g. |
119 | if something is a string or a glob, it's important that L<UNIVERSAL::ref> |
120 | is loaded before TT is. We check to see if the latter is loaded and the |
121 | former not, and warn loudly that you're probably going to get weird errors. |
122 | |
123 | This warning is not joking. "Probably" is optimistic. Load this module first. |
124 | |
125 | =head1 FILTERS |
126 | |
127 | =head2 no_escape |
128 | |
129 | The C<no_escape> filter marks the filtered input to not be escaped, |
130 | so that you can provide HTML chunks from externally and still render them |
131 | within the TT code. |
132 | |
133 | =head1 AUTHORS |
134 | |
135 | See L<HTML::String> for authors. |
136 | |
137 | =head1 COPYRIGHT AND LICENSE |
138 | |
139 | See L<HTML::String> for the copyright and license. |
140 | |
141 | =cut |