Part convert, not working entirely yet
[catagits/Catalyst-View-TT.git] / lib / Catalyst / View / TT.pm
CommitLineData
8077080c 1package Catalyst::View::TT;
2e322ce3 2use Moose;
9e739e1e 3use Data::Dump 'dump';
8077080c 4use Template;
5use Template::Timer;
e8693f1b 6use MRO::Compat;
316f014a 7use Scalar::Util qw/blessed/;
2e322ce3 8use namespace::autoclean;
9
10extends 'Catalyst::View';
8077080c 11
bd45975e 12our $VERSION = '0.33';
8077080c 13
2e322ce3 14has template => ( is => 'ro' );
15has include_path => ( is => 'rw' );
8077080c 16
2e322ce3 17__PACKAGE__->meta->add_method('paths' => __PACKAGE__->meta->find_method_by_name('include_path'));
9d574573 18
8077080c 19=head1 NAME
20
21Catalyst::View::TT - Template View Class
22
23=head1 SYNOPSIS
24
bd4ee63a 25# use the helper to create your View
ad50568f 26
2e322ce3 27 myapp_create.pl view HTML TT
8077080c 28
6175bba7 29# configure in lib/MyApp.pm (Could be set from configfile instead)
8cd017a8 30
940a2e8a 31 __PACKAGE__->config(
32 name => 'MyApp',
33 root => MyApp->path_to('root'),
34 default_view => 'TT',
2e322ce3 35 'View::HTML' => {
8cd017a8 36 # any TT configurations items go here
37 INCLUDE_PATH => [
f5b61ad7 38 MyApp->path_to( 'root', 'src' ),
39 MyApp->path_to( 'root', 'lib' ),
8cd017a8 40 ],
6175bba7 41 TEMPLATE_EXTENSION => '.tt',
42 CATALYST_VAR => 'c',
43 TIMER => 0,
44 # Not set by default
07571b2f 45 PRE_PROCESS => 'config/main',
46 WRAPPER => 'site/wrapper',
3715305f 47 render_die => 1, # Default for new apps, see render method docs
8cd017a8 48 },
ae035767 49 );
f5b61ad7 50
6229ce0d 51# render view from lib/MyApp.pm or lib/MyApp::Controller::SomeController.pm
f5b61ad7 52
8cd017a8 53 sub message : Global {
94b3529a 54 my ( $self, $c ) = @_;
55 $c->stash->{template} = 'message.tt2';
56 $c->stash->{message} = 'Hello World!';
c18eae32 57 $c->forward( $c->view('TT') );
8cd017a8 58 }
8077080c 59
8cd017a8 60# access variables from template
61
62 The message is: [% message %].
f5b61ad7 63
8cd017a8 64 # example when CATALYST_VAR is set to 'Catalyst'
f5b61ad7 65 Context is [% Catalyst %]
66 The base is [% Catalyst.req.base %]
67 The name is [% Catalyst.config.name %]
68
8cd017a8 69 # example when CATALYST_VAR isn't set
70 Context is [% c %]
71 The base is [% base %]
72 The name is [% name %]
73
bd4ee63a 74=cut
75
76sub _coerce_paths {
77 my ( $paths, $dlim ) = shift;
78 return () if ( !$paths );
79 return @{$paths} if ( ref $paths eq 'ARRAY' );
80
81 # tweak delim to ignore C:/
82 unless ( defined $dlim ) {
83 $dlim = ( $^O eq 'MSWin32' ) ? ':(?!\\/)' : ':';
84 }
85 return split( /$dlim/, $paths );
86}
87
2e322ce3 88#$class->merge_config_hashes( $class->config, $args );
89
90around BUILDARGS => sub {
91 my ( $orig, $class, $c, $arguments ) = @_;
92 my $config = $class->merge_config_hashes(
93 {
94 EVAL_PERL => 0,
95 TEMPLATE_EXTENSION => '',
96 },
97 $class->$orig($c, $arguments)
98 );
bd4ee63a 99 if ( ! (ref $config->{INCLUDE_PATH} eq 'ARRAY') ) {
100 my $delim = $config->{DELIMITER};
101 my @include_path
102 = _coerce_paths( $config->{INCLUDE_PATH}, $delim );
103 if ( !@include_path ) {
104 my $root = $c->config->{root};
105 my $base = Path::Class::dir( $root, 'base' );
106 @include_path = ( "$root", "$base" );
107 }
108 $config->{INCLUDE_PATH} = \@include_path;
109 }
110
111 # if we're debugging and/or the TIMER option is set, then we install
112 # Template::Timer as a custom CONTEXT object, but only if we haven't
113 # already got a custom CONTEXT defined
114
115 if ( $config->{TIMER} ) {
116 if ( $config->{CONTEXT} ) {
117 $c->log->error(
118 'Cannot use Template::Timer - a TT CONTEXT is already defined'
119 );
120 }
121 else {
122 $config->{CONTEXT} = Template::Timer->new(%$config);
123 }
124 }
125
126 if ( $c->debug && $config->{DUMP_CONFIG} ) {
9e739e1e 127 $c->log->debug( "TT Config: ", dump($config) );
bd4ee63a 128 }
6175bba7 129
bd4ee63a 130 if ( $config->{PROVIDERS} ) {
131 my @providers = ();
132 if ( ref($config->{PROVIDERS}) eq 'ARRAY') {
133 foreach my $p (@{$config->{PROVIDERS}}) {
134 my $pname = $p->{name};
135 my $prov = 'Template::Provider';
136 if($pname eq '_file_')
137 {
138 $p->{args} = { %$config };
139 }
140 else
141 {
51199593 142 if($pname =~ s/^\+//) {
143 $prov = $pname;
144 }
145 else
146 {
147 $prov .= "::$pname";
148 }
6175bba7 149 # We copy the args people want from the config
150 # to the args
151 $p->{args} ||= {};
152 if ($p->{copy_config}) {
153 map { $p->{args}->{$_} = $config->{$_} }
154 grep { exists $config->{$_} }
155 @{ $p->{copy_config} };
156 }
bd4ee63a 157 }
fc0ffed0 158 local $@;
bd4ee63a 159 eval "require $prov";
160 if(!$@) {
161 push @providers, "$prov"->new($p->{args});
162 }
163 else
164 {
165 $c->log->warn("Can't load $prov, ($@)");
166 }
167 }
168 }
169 delete $config->{PROVIDERS};
170 if(@providers) {
171 $config->{LOAD_TEMPLATES} = \@providers;
172 }
173 }
f5b61ad7 174
2e322ce3 175 $config->{template} =
bd4ee63a 176 Template->new($config) || do {
177 my $error = Template->error();
178 $c->log->error($error);
179 $c->error($error);
180 return undef;
181 };
182
2e322ce3 183 return $config;
184};
185
186sub BUILD {
187 my ($self, $config) = @_;
188 # Set base include paths. Local'd in render if needed
189 $self->include_path($config->{INCLUDE_PATH});
190
191 $self->config($config);
bd4ee63a 192
2e322ce3 193 # Creation of template outside of call to new so that we can pass [ $self ]
194 # as INCLUDE_PATH config item, which then gets ->paths() called to get list
195 # of include paths to search for templates.
196
197 # Use a weakend copy of self so we dont have loops preventing GC from working
198 my $copy = $self;
199 Scalar::Util::weaken($copy);
200 $config->{INCLUDE_PATH} = [ sub { $copy->paths } ];
bd4ee63a 201}
202
203sub process {
204 my ( $self, $c ) = @_;
205
206 my $template = $c->stash->{template}
207 || $c->action . $self->config->{TEMPLATE_EXTENSION};
208
209 unless (defined $template) {
210 $c->log->debug('No template specified for rendering') if $c->debug;
211 return 0;
212 }
213
fc0ffed0 214 local $@;
cad820fe 215 my $output = eval { $self->render($c, $template) };
216 if (my $err = $@) {
316f014a 217 return $self->_rendering_error($c, $err);
218 }
219 if (blessed($output) && $output->isa('Template::Exception')) {
220 $self->_rendering_error($c, $output);
bd4ee63a 221 }
222
223 unless ( $c->response->content_type ) {
224 $c->response->content_type('text/html; charset=utf-8');
225 }
226
227 $c->response->body($output);
228
229 return 1;
230}
231
316f014a 232sub _rendering_error {
233 my ($self, $c, $err) = @_;
234 my $error = qq/Couldn't render template "$err"/;
235 $c->log->error($error);
236 $c->error($error);
237 return 0;
238}
239
bd4ee63a 240sub render {
241 my ($self, $c, $template, $args) = @_;
242
cbb149dc 243 $c->log->debug(qq/Rendering template "$template"/) if $c && $c->debug;
bd4ee63a 244
245 my $output;
f5b61ad7 246 my $vars = {
bd4ee63a 247 (ref $args eq 'HASH' ? %$args : %{ $c->stash() }),
248 $self->template_vars($c)
249 };
250
f5b61ad7 251 local $self->{include_path} =
bd4ee63a 252 [ @{ $vars->{additional_template_paths} }, @{ $self->{include_path} } ]
253 if ref $vars->{additional_template_paths};
254
596ff245 255 unless ( $self->template->process( $template, $vars, \$output ) ) {
256 if (exists $self->{render_die}) {
257 die $self->template->error if $self->{render_die};
258 return $self->template->error;
259 }
316f014a 260 $c->log->debug('The Catalyst::View::TT render() method of will die on error in a future release. Unless you are calling the render() method manually, you probably want the new behaviour, so set render_die => 1 in config for ' . blessed($self) . '. If you are calling the render() method manually and you wish it to continue to return the exception rather than throwing it, add render_die => 0 to your config.') if $c->debug;
596ff245 261 return $self->template->error;
262 }
cad820fe 263 return $output;
bd4ee63a 264}
265
266sub template_vars {
267 my ( $self, $c ) = @_;
268
cbb149dc 269 return () unless $c;
bd4ee63a 270 my $cvar = $self->config->{CATALYST_VAR};
271
272 defined $cvar
273 ? ( $cvar => $c )
274 : (
275 c => $c,
276 base => $c->req->base,
277 name => $c->config->{name}
278 )
279}
280
281
2821;
283
284__END__
285
8cd017a8 286=head1 DESCRIPTION
287
288This is the Catalyst view class for the L<Template Toolkit|Template>.
289Your application should defined a view class which is a subclass of
290this module. The easiest way to achieve this is using the
291F<myapp_create.pl> script (where F<myapp> should be replaced with
292whatever your application is called). This script is created as part
293of the Catalyst setup.
294
295 $ script/myapp_create.pl view TT TT
296
6229ce0d 297This creates a MyApp::View::TT.pm module in the F<lib> directory (again,
8cd017a8 298replacing C<MyApp> with the name of your application) which looks
299something like this:
300
6229ce0d 301 package FooBar::View::TT;
f5b61ad7 302
8cd017a8 303 use strict;
c18eae32 304 use warnings;
f5b61ad7 305
c18eae32 306 use base 'Catalyst::View::TT';
8077080c 307
a1b7968f 308 __PACKAGE__->config(DEBUG => 'all');
8077080c 309
8cd017a8 310Now you can modify your action handlers in the main application and/or
311controllers to forward to your view class. You might choose to do this
312in the end() method, for example, to automatically forward all actions
313to the TT view class.
722fede4 314
8cd017a8 315 # In MyApp or MyApp::Controller::SomeController
f5b61ad7 316
8cd017a8 317 sub end : Private {
94b3529a 318 my( $self, $c ) = @_;
c18eae32 319 $c->forward( $c->view('TT') );
8cd017a8 320 }
8077080c 321
2844488f 322But if you are using the standard auto-generated end action, you don't even need
323to do this!
324
325 # in MyApp::Controller::Root
326 sub end : ActionClass('RenderView') {} # no need to change this line
327
328 # in MyApp.pm
329 __PACKAGE__->config(
330 ...
331 default_view => 'TT',
332 );
333
334This will Just Work. And it has the advantages that:
335
336=over 4
337
338=item *
339
340If you want to use a different view for a given request, just set
341<< $c->stash->{current_view} >>. (See L<Catalyst>'s C<< $c->view >> method
342for details.
343
344=item *
345
346<< $c->res->redirect >> is handled by default. If you just forward to
347C<View::TT> in your C<end> routine, you could break this by sending additional
348content.
349
350=back
351
352See L<Catalyst::Action::RenderView> for more details.
353
8cd017a8 354=head2 CONFIGURATION
4687ac0d 355
8cd017a8 356There are a three different ways to configure your view class. The
357first way is to call the C<config()> method in the view subclass. This
358happens when the module is first loaded.
8077080c 359
6229ce0d 360 package MyApp::View::TT;
f5b61ad7 361
8cd017a8 362 use strict;
363 use base 'Catalyst::View::TT';
722fede4 364
6229ce0d 365 MyApp::View::TT->config({
7d8aa5ec 366 INCLUDE_PATH => [
367 MyApp->path_to( 'root', 'templates', 'lib' ),
368 MyApp->path_to( 'root', 'templates', 'src' ),
369 ],
8cd017a8 370 PRE_PROCESS => 'config/main',
371 WRAPPER => 'site/wrapper',
372 });
373
374The second way is to define a C<new()> method in your view subclass.
375This performs the configuration when the view object is created,
376shortly after being loaded. Remember to delegate to the base class
e8693f1b 377C<new()> method (via C<$self-E<gt>next::method()> in the example below) after
8cd017a8 378performing any configuration.
379
380 sub new {
381 my $self = shift;
382 $self->config({
7d8aa5ec 383 INCLUDE_PATH => [
384 MyApp->path_to( 'root', 'templates', 'lib' ),
385 MyApp->path_to( 'root', 'templates', 'src' ),
386 ],
8cd017a8 387 PRE_PROCESS => 'config/main',
388 WRAPPER => 'site/wrapper',
389 });
e8693f1b 390 return $self->next::method(@_);
8cd017a8 391 }
f5b61ad7 392
94b3529a 393The final, and perhaps most direct way, is to define a class
8cd017a8 394item in your main application configuration, again by calling the
ad50568f 395ubiquitous C<config()> method. The items in the class hash are
8cd017a8 396added to those already defined by the above two methods. This happens
397in the base class new() method (which is one reason why you must
f5b61ad7 398remember to call it via C<MRO::Compat> if you redefine the C<new()>
e8693f1b 399method in a subclass).
8cd017a8 400
401 package MyApp;
f5b61ad7 402
8cd017a8 403 use strict;
404 use Catalyst;
f5b61ad7 405
8cd017a8 406 MyApp->config({
407 name => 'MyApp',
7d8aa5ec 408 root => MyApp->path_to('root'),
6229ce0d 409 'View::TT' => {
7d8aa5ec 410 INCLUDE_PATH => [
411 MyApp->path_to( 'root', 'templates', 'lib' ),
412 MyApp->path_to( 'root', 'templates', 'src' ),
413 ],
8cd017a8 414 PRE_PROCESS => 'config/main',
415 WRAPPER => 'site/wrapper',
416 },
417 });
418
419Note that any configuration items defined by one of the earlier
420methods will be overwritten by items of the same name provided by the
f5b61ad7 421latter methods.
8cd017a8 422
e2bbd784 423=head2 DYNAMIC INCLUDE_PATH
424
f7dfca06 425Sometimes it is desirable to modify INCLUDE_PATH for your templates at run time.
f5b61ad7 426
f7dfca06 427Additional paths can be added to the start of INCLUDE_PATH via the stash as
428follows:
429
430 $c->stash->{additional_template_paths} =
431 [$c->config->{root} . '/test_include_path'];
432
433If you need to add paths to the end of INCLUDE_PATH, there is also an
434include_path() accessor available:
435
436 push( @{ $c->view('TT')->include_path }, qw/path/ );
437
438Note that if you use include_path() to add extra paths to INCLUDE_PATH, you
439MUST check for duplicate paths. Without such checking, the above code will add
440"path" to INCLUDE_PATH at every request, causing a memory leak.
441
442A safer approach is to use include_path() to overwrite the array of paths
443rather than adding to it. This eliminates both the need to perform duplicate
444checking and the chance of a memory leak:
e2bbd784 445
f7dfca06 446 @{ $c->view('TT')->include_path } = qw/path another_path/;
e2bbd784 447
f5b61ad7 448If you are calling C<render> directly then you can specify dynamic paths by
9d574573 449having a C<additional_template_paths> key with a value of additonal directories
1bc9fc55 450to search. See L<CAPTURING TEMPLATE OUTPUT> for an example showing this.
451
8cd017a8 452=head2 RENDERING VIEWS
453
454The view plugin renders the template specified in the C<template>
f5b61ad7 455item in the stash.
8cd017a8 456
457 sub message : Global {
94b3529a 458 my ( $self, $c ) = @_;
459 $c->stash->{template} = 'message.tt2';
6229ce0d 460 $c->forward( $c->view('TT') );
8cd017a8 461 }
722fede4 462
c969f23a 463If a stash item isn't defined, then it instead uses the
464stringification of the action dispatched to (as defined by $c->action)
465in the above example, this would be C<message>, but because the default
466is to append '.tt', it would load C<root/message.tt>.
8cd017a8 467
468The items defined in the stash are passed to the Template Toolkit for
469use as template variables.
470
8cd017a8 471 sub default : Private {
94b3529a 472 my ( $self, $c ) = @_;
473 $c->stash->{template} = 'message.tt2';
474 $c->stash->{message} = 'Hello World!';
6229ce0d 475 $c->forward( $c->view('TT') );
8cd017a8 476 }
7b592fc7 477
8cd017a8 478A number of other template variables are also added:
8077080c 479
8cd017a8 480 c A reference to the context object, $c
481 base The URL base, from $c->req->base()
482 name The application name, from $c->config->{ name }
483
484These can be accessed from the template in the usual way:
485
486<message.tt2>:
487
488 The message is: [% message %]
489 The base is [% base %]
490 The name is [% name %]
491
8cd017a8 492
1bc9fc55 493The output generated by the template is stored in C<< $c->response->body >>.
494
495=head2 CAPTURING TEMPLATE OUTPUT
496
497If you wish to use the output of a template for some other purpose than
498displaying in the response, e.g. for sending an email, this is possible using
499L<Catalyst::Plugin::Email> and the L<render> method:
500
501 sub send_email : Local {
502 my ($self, $c) = @_;
f5b61ad7 503
1bc9fc55 504 $c->email(
505 header => [
506 To => 'me@localhost',
507 Subject => 'A TT Email',
508 ],
509 body => $c->view('TT')->render($c, 'email.tt', {
9d574573 510 additional_template_paths => [ $c->config->{root} . '/email_templates'],
1bc9fc55 511 email_tmpl_param1 => 'foo'
512 }
513 ),
514 );
515 # Redirect or display a message
516 }
8cd017a8 517
518=head2 TEMPLATE PROFILING
519
1bc9fc55 520See L<C<TIMER>> property of the L<config> method.
521
caa61517 522=head2 METHODS
8077080c 523
b63ddd04 524=head2 new
2774dc77 525
f5b61ad7 526The constructor for the TT view. Sets up the template provider,
2774dc77 527and reads the application config.
528
81b7f2a2 529=head2 process($c)
8077080c 530
1bc9fc55 531Renders the template specified in C<< $c->stash->{template} >> or
ad50568f 532C<< $c->action >> (the private name of the matched action). Calls L<render> to
1bc9fc55 533perform actual rendering. Output is stored in C<< $c->response->body >>.
8077080c 534
81b7f2a2 535It is possible to forward to the process method of a TT view from inside
536Catalyst like this:
537
538 $c->forward('View::TT');
539
540N.B. This is usually done automatically by L<Catalyst::Action::RenderView>.
f2ee4d6c 541
b63ddd04 542=head2 render($c, $template, \%args)
1bc9fc55 543
cad820fe 544Renders the given template and returns output. Throws a L<Template::Exception>
f5b61ad7 545object upon error.
1bc9fc55 546
f5b61ad7 547The template variables are set to C<%$args> if $args is a hashref, or
548$C<< $c->stash >> otherwise. In either case the variables are augmented with
1bc9fc55 549C<base> set to C< << $c->req->base >>, C<c> to C<$c> and C<name> to
550C<< $c->config->{name} >>. Alternately, the C<CATALYST_VAR> configuration item
551can be defined to specify the name of a template variable through which the
552context reference (C<$c>) can be accessed. In this case, the C<c>, C<base> and
553C<name> variables are omitted.
554
f5b61ad7 555C<$template> can be anything that Template::process understands how to
1bc9fc55 556process, including the name of a template file or a reference to a test string.
557See L<Template::process|Template/process> for a full list of supported formats.
558
f59953e1 559To use the render method outside of your Catalyst app, just pass a undef context.
cbb149dc 560This can be useful for tests, for instance.
561
81b7f2a2 562It is possible to forward to the render method of a TT view from inside Catalyst
563to render page fragments like this:
564
565 my $fragment = $c->forward("View::TT", "render", $template_name, $c->stash->{fragment_data});
f2ee4d6c 566
3715305f 567=head3 Backwards compatibility note
568
569The render method used to just return the Template::Exception object, rather
570than just throwing it. This is now deprecated and instead the render method
571will throw an exception for new applications.
572
573This behaviour can be activated (and is activated in the default skeleton
574configuration) by using C<< render_die => 1 >>. If you rely on the legacy
575behaviour then a warning will be issued.
576
577To silence this warning, set C<< render_die => 0 >>, but it is recommended
578you adjust your code so that it works with C<< render_die => 1 >>.
579
580In a future release, C<< render_die => 1 >> will become the default if
581unspecified.
582
b63ddd04 583=head2 template_vars
850ee226 584
1bc9fc55 585Returns a list of keys/values to be used as the catalyst variables in the
850ee226 586template.
587
b63ddd04 588=head2 config
8077080c 589
8cd017a8 590This method allows your view subclass to pass additional settings to
4729c102 591the TT configuration hash, or to set the options as below:
592
b63ddd04 593=head2 paths
594
595The list of paths TT will look for templates in.
4729c102 596
f5b61ad7 597=head2 C<CATALYST_VAR>
4729c102 598
599Allows you to change the name of the Catalyst context object. If set, it will also
600remove the base and name aliases, so you will have access them through <context>.
601
602For example:
603
604 MyApp->config({
605 name => 'MyApp',
7d8aa5ec 606 root => MyApp->path_to('root'),
6229ce0d 607 'View::TT' => {
4729c102 608 CATALYST_VAR => 'Catalyst',
609 },
610 });
611
612F<message.tt2>:
613
614 The base is [% Catalyst.req.base %]
615 The name is [% Catalyst.config.name %]
616
b63ddd04 617=head2 C<TIMER>
4729c102 618
619If you have configured Catalyst for debug output, and turned on the TIMER setting,
620C<Catalyst::View::TT> will enable profiling of template processing
621(using L<Template::Timer>). This will embed HTML comments in the
622output from your templates, such as:
623
624 <!-- TIMER START: process mainmenu/mainmenu.ttml -->
625 <!-- TIMER START: include mainmenu/cssindex.tt -->
626 <!-- TIMER START: process mainmenu/cssindex.tt -->
627 <!-- TIMER END: process mainmenu/cssindex.tt (0.017279 seconds) -->
628 <!-- TIMER END: include mainmenu/cssindex.tt (0.017401 seconds) -->
629
630 ....
631
632 <!-- TIMER END: process mainmenu/footer.tt (0.003016 seconds) -->
633
634
b63ddd04 635=head2 C<TEMPLATE_EXTENSION>
4729c102 636
747f2b6d 637a sufix to add when looking for templates bases on the C<match> method in L<Catalyst::Request>.
4729c102 638
639For example:
640
6229ce0d 641 package MyApp::Controller::Test;
f5b61ad7 642 sub test : Local { .. }
4729c102 643
644Would by default look for a template in <root>/test/test. If you set TEMPLATE_EXTENSION to '.tt', it will look for
645<root>/test/test.tt.
646
51199593 647=head2 C<PROVIDERS>
648
649Allows you to specify the template providers that TT will use.
650
651 MyApp->config({
652 name => 'MyApp',
653 root => MyApp->path_to('root'),
6229ce0d 654 'View::TT' => {
51199593 655 PROVIDERS => [
656 {
657 name => 'DBI',
658 args => {
659 DBI_DSN => 'dbi:DB2:books',
660 DBI_USER=> 'foo'
661 }
662 }, {
663 name => '_file_',
664 args => {}
665 }
666 ]
667 },
668 });
669
670The 'name' key should correspond to the class name of the provider you
671want to use. The _file_ name is a special case that represents the default
672TT file-based provider. By default the name is will be prefixed with
673'Template::Provider::'. You can fully qualify the name by using a unary
674plus:
675
676 name => '+MyApp::Provider::Foo'
677
6175bba7 678You can also specify the 'copy_config' key as an arrayref, to copy those keys
679from the general config, into the config for the provider:
f5b61ad7 680
6175bba7 681 DEFAULT_ENCODING => 'utf-8',
682 PROVIDERS => [
683 {
684 name => 'Encoding',
685 copy_config => [qw(DEFAULT_ENCODING INCLUDE_PATH)]
686 }
687 ]
f5b61ad7 688
6175bba7 689This can prove useful when you want to use the additional_template_paths hack
690in your own provider, or if you need to use Template::Provider::Encoding
691
8cd017a8 692=head2 HELPERS
693
694The L<Catalyst::Helper::View::TT> and
695L<Catalyst::Helper::View::TTSite> helper modules are provided to create
696your view module. There are invoked by the F<myapp_create.pl> script:
697
698 $ script/myapp_create.pl view TT TT
699
700 $ script/myapp_create.pl view TT TTSite
701
702The L<Catalyst::Helper::View::TT> module creates a basic TT view
703module. The L<Catalyst::Helper::View::TTSite> module goes a little
704further. It also creates a default set of templates to get you
705started. It also configures the view module to locate the templates
706automatically.
707
02c64502 708=head1 NOTES
709
710If you are using the L<CGI> module inside your templates, you will
711experience that the Catalyst server appears to hang while rendering
712the web page. This is due to the debug mode of L<CGI> (which is
713waiting for input in the terminal window). Turning off the
714debug mode using the "-no_debug" option solves the
715problem, eg.:
716
717 [% USE CGI('-no_debug') %]
718
8077080c 719=head1 SEE ALSO
720
8cd017a8 721L<Catalyst>, L<Catalyst::Helper::View::TT>,
722L<Catalyst::Helper::View::TTSite>, L<Template::Manual>
8077080c 723
c0eb0527 724=head1 AUTHORS
8077080c 725
726Sebastian Riedel, C<sri@cpan.org>
c0eb0527 727
d938377b 728Marcus Ramberg, C<mramberg@cpan.org>
c0eb0527 729
722fede4 730Jesse Sheidlower, C<jester@panix.com>
c0eb0527 731
8cd017a8 732Andy Wardley, C<abw@cpan.org>
8077080c 733
734=head1 COPYRIGHT
735
f5b61ad7 736This program is free software. You can redistribute it and/or modify it
2774dc77 737under the same terms as Perl itself.
8077080c 738
739=cut