Newer Older
1180 lines | 32.593kb
copy gitweblite soruce code
root authored on 2012-11-23
1

            
2
=encoding utf8
3

            
4
=head1 NAME
5

            
6
Mojolicious::Guides::Rendering - Rendering
7

            
8
=head1 OVERVIEW
9

            
10
This document explains content generation with the L<Mojolicious> renderer.
11

            
12
=head1 CONCEPTS
13

            
14
Essentials every L<Mojolicious> developer should know.
15

            
16
=head2 Renderer
17

            
18
The renderer is a tiny black box turning stash data into actual responses
19
utilizing multiple template systems and data encoding modules.
20

            
21
  {text => 'Hello.'}                 -> 200 OK, text/html, 'Hello.'
22
  {json => {x => 3}}                 -> 200 OK, application/json, '{"x":3}'
23
  {text => 'Oops.', status => '410'} -> 410 Gone, text/html, 'Oops.'
24

            
25
Templates can be automatically detected if enough information is provided by
26
the developer or routes. Template names are expected to follow the
27
C<name.format.handler> scheme, with C<name> defaulting to C<controller/action>
28
or the route name, C<format> defaulting to C<html> and C<handler> to C<ep>.
29

            
30
  {controller => 'users', action => 'list'} -> 'users/list.html.ep'
31
  {name => 'foo', format => 'txt'}          -> 'foo.txt.ep'
32
  {name => 'foo', handler => 'epl'}         -> 'foo.html.epl'
33

            
34
All templates should be in the C<templates> directories of the application or
35
the C<DATA> section of the class C<main>.
36

            
37
  __DATA__
38

            
39
  @@ time.html.ep
40
  % use Time::Piece;
41
  % my $now = localtime;
42
  <!DOCTYPE html>
43
  <html>
44
    <head><title>Time</title></head>
45
    <body>The time is <%= $now->hms %>.</body>
46
  </html>
47

            
48
  @@ hello.txt.ep
49
  ...
50

            
51
The renderer can be easily extended to support additional template systems
52
with plugins, but more about that later.
53

            
54
=head2 Embedded Perl
55

            
56
L<Mojolicious> includes a minimalistic but very powerful template system out
57
of the box called Embedded Perl or C<ep> for short. It allows the embedding of
58
Perl code right into actual content using a small set of special tags and line
59
start characters.
60

            
61
  <% Perl code %>
62
  <%= Perl expression, replaced with XML escaped result %>
63
  <%== Perl expression, replaced with result %>
64
  <%# Comment, useful for debugging %>
65
  <%% Replaced with "<%", useful for generating templates %>
66
  % Perl code line, treated as "<% line =%>"
67
  %= Perl expression line, treated as "<%= line %>"
68
  %== Perl expression line, treated as "<%== line %>"
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
69
  %# Comment line, useful for debugging
copy gitweblite soruce code
root authored on 2012-11-23
70
  %% Replaced with "%", useful for generating templates
71

            
72
Tags and lines work pretty much the same, but depending on context one will
73
usually look a bit better. Semicolons get automatically appended to all
74
expressions.
75

            
76
  <% my $i = 10; %>
77
  <ul>
78
    <% for my $j (1 .. $i) { %>
79
      <li>
80
        <%= $j %>
81
      </li>
82
    <% } %>
83
  </ul>
84

            
85
  % my $i = 10;
86
  <ul>
87
    % for my $j (1 .. $i) {
88
      <li>
89
        %= $j
90
      </li>
91
    % }
92
  </ul>
93

            
94
Aside from differences in whitespace handling, both examples generate similar
95
Perl code, a naive translation could look like this.
96

            
97
  my $output = '';
98
  my $i = 10;
99
  $output .= '<ul>';
100
  for my $j (1 .. $i) {
101
    $output .= '<li>';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
102
    $output .= xml_escape scalar $j;
copy gitweblite soruce code
root authored on 2012-11-23
103
    $output .= '</li>';
104
  }
105
  $output .= '</ul>';
106
  return $output;
107

            
108
An additional equal sign can be used to disable escaping of the characters
109
C<E<lt>>, C<E<gt>>, C<&>, C<'> and C<"> in results from Perl expressions,
110
which is the default to prevent XSS attacks against your application.
111

            
112
  <%= 'lalala' %>
113
  <%== '<p>test</p>' %>
114

            
115
Only L<Mojo::ByteStream> objects are excluded from automatic escaping.
116

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
117
  % use Mojo::ByteStream 'b';
118
  <%= b('<p>test</p>') %>
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
119

            
120
Newline characters can be escaped with a backslash.
121

            
122
  This is <%= 1 + 1 %> a\
123
  single line
124

            
125
And a backslash in front of a newline character can be escaped with another
126
backslash.
127

            
128
  This will <%= 1 + 1 %> result\\
129
  in multiple\\
130
  lines
copy gitweblite soruce code
root authored on 2012-11-23
131

            
132
You can also add an additional equal sign to the end of a tag to have it
133
automatically remove all surrounding whitespace, this allows free indenting
134
without ruining the result.
135

            
136
  <% for (1 .. 3) { %>
137
    <%= $foo =%>
138
  <% } %>
139

            
140
Stash values that don't have invalid characters in their name get
141
automatically initialized as normal variables in the template, and the
142
controller object as C<$self>.
143

            
144
  $self->stash(name => 'tester');
145

            
146
  Hello <%= $name %> from <%= $self->tx->remote_address %>.
147

            
148
There are also many helper functions available, but more about that later.
149

            
150
  <%= dumper {foo => 'bar'} %>
151

            
152
=head1 BASICS
153

            
154
Most commonly used features every L<Mojolicious> developer should know about.
155

            
156
=head2 Automatic rendering
157

            
158
The renderer can be manually started by calling the method
159
L<Mojolicious::Controller/"render">, but that's usually not necessary,
160
because it will get automatically called if nothing has been rendered after
161
the router finished its work. This also means you can have routes pointing
162
only to templates without actual actions.
163

            
164
  $self->render;
165

            
166
There is one big difference though, by calling it manually you can make sure
167
that templates use the current controller object, and not the default
168
controller specified with the attribute L<Mojolicious/"controller_class">.
169

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
170
  $self->render_later;
171

            
172
You can also disable automatic rendering with the method
173
L<Mojolicious::Controller/"render_later">, which can be very useful to delay
174
rendering when a non-blocking operation has to be performed first.
175

            
copy gitweblite soruce code
root authored on 2012-11-23
176
=head2 Rendering templates
177

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
178
The renderer will always try to detect the right template, but you can also
179
use the C<template> stash value to render a specific one. Everything before
180
the last slash will be interpreted as the subdirectory path in which to find
181
the template.
copy gitweblite soruce code
root authored on 2012-11-23
182

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
183
  # foo/bar/baz.*.*
184
  $self->render(template => 'foo/bar/baz');
copy gitweblite soruce code
root authored on 2012-11-23
185

            
186
Choosing a specific C<format> and C<handler> is just as easy.
187

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
188
  # foo/bar/baz.txt.epl
189
  $self->render(template => 'foo/bar/baz', format => 'txt', handler => 'epl');
copy gitweblite soruce code
root authored on 2012-11-23
190

            
191
Because rendering a specific template is the most common task it also has a
192
shortcut.
193

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
194
  $self->render('foo/bar/baz');
195

            
196
If you're not sure in advance if a template actually exists, you can also use
197
the method L<Mojolicious::Controller/"render_maybe"> to try multiple
198
alternatives.
199

            
200
  $self->render_maybe('localized/baz') or $self->render('foo/bar/baz');
copy gitweblite soruce code
root authored on 2012-11-23
201

            
202
=head2 Rendering inline templates
203

            
204
Some renderers such as C<ep> allow templates to be passed inline.
205

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
206
  $self->render(inline => 'The result is <%= 1 + 1 %>.');
copy gitweblite soruce code
root authored on 2012-11-23
207

            
208
Since auto detection depends on a path you might have to supply a C<handler>
209
too.
210

            
211
  $self->render(inline => "<%= shift->param('foo') %>", handler => 'epl');
212

            
213
=head2 Rendering text
214

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
215
Characters can be rendered to bytes with the C<text> stash value, the given
copy gitweblite soruce code
root authored on 2012-11-23
216
content will be automatically encoded to bytes.
217

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
218
  $self->render(text => 'I ♥ Mojolicious!');
copy gitweblite soruce code
root authored on 2012-11-23
219

            
220
=head2 Rendering data
221

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
222
Bytes can be rendered with the C<data> stash value, no encoding will be
copy gitweblite soruce code
root authored on 2012-11-23
223
performed.
224

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
225
  $self->render(data => $bytes);
copy gitweblite soruce code
root authored on 2012-11-23
226

            
227
=head2 Rendering JSON
228

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
229
The C<json> stash value allows you to pass Perl data structures to the
230
renderer which get directly encoded to JSON.
copy gitweblite soruce code
root authored on 2012-11-23
231

            
232
  $self->render(json => {foo => [1, 'test', 3]});
233

            
234
=head2 Partial rendering
235

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
236
Sometimes you might want to use the rendered result directly instead of
237
generating a response, for example to send emails, this can be done using the
238
C<partial> stash value.
copy gitweblite soruce code
root authored on 2012-11-23
239

            
240
  my $html = $self->render('mail', partial => 1);
241

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
242
No encoding will be performed, making it easy to reuse the result in other
243
templates or to generate binary data.
244

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
245
  my $pdf = $self->render('invoice', format => 'pdf', partial => 1);
246
  $self->render(data => $pdf, format => 'pdf');
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
247

            
copy gitweblite soruce code
root authored on 2012-11-23
248
=head2 Status code
249

            
250
Response status codes can be changed with the C<status> stash value.
251

            
252
  $self->render(text => 'Oops.', status => 500);
253

            
254
=head2 Content type
255

            
256
The C<Content-Type> header of the response is actually based on the MIME type
257
mapping of the C<format> stash value.
258

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
259
  # Content-Type: text/plain
copy gitweblite soruce code
root authored on 2012-11-23
260
  $self->render(text => 'Hello.', format => 'txt');
261

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
262
  # Content-Type: image/png
263
  $self->render(data => $bytes, format => 'png');
264

            
copy gitweblite soruce code
root authored on 2012-11-23
265
These mappings can be easily extended or changed with L<Mojolicious/"types">.
266

            
267
  # Application
268
  package MyApp;
269
  use Mojo::Base 'Mojolicious';
270

            
271
  sub startup {
272
    my $self = shift;
273

            
274
    # Add new MIME type
275
    $self->types->type(txt => 'text/plain; charset=utf-8');
276
  }
277

            
278
  1;
279

            
280
=head2 Stash data
281

            
282
Any of the native Perl data types can be passed to templates through the
283
L<Mojolicious::Controller/"stash">.
284

            
285
  $self->stash(author     => 'Sebastian');
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
286
  $self->stash(frameworks => [qw(Catalyst Mojolicious)]);
copy gitweblite soruce code
root authored on 2012-11-23
287
  $self->stash(examples   => {tweetylicious => 'a microblogging app'});
288

            
289
  %= $author
290
  %= $frameworks->[1]
291
  %= $examples->{tweetylicious}
292

            
293
Since everything is just Perl normal control structures just work.
294

            
295
  % for my $framework (@$frameworks) {
296
    <%= $framework %> was written by <%= $author %>.
297
  % }
298

            
299
  % while (my ($app, $description) = each %$examples) {
300
    <%= $app %> is a <%= $description %>.
301
  % }
302

            
303
=head2 Content negotiation
304

            
305
For resources with different representations and that require truly
306
C<RESTful> content negotiation you can also use
307
L<Mojolicious::Controller/"respond_to"> instead of
308
L<Mojolicious::Controller/"render">.
309

            
310
  # /hello (Accept: application/json) -> "json"
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
311
  # /hello (Accept: application/xml)  -> "xml"
copy gitweblite soruce code
root authored on 2012-11-23
312
  # /hello.json                       -> "json"
313
  # /hello.xml                        -> "xml"
314
  # /hello?format=json                -> "json"
315
  # /hello?format=xml                 -> "xml"
316
  $self->respond_to(
317
    json => {json => {hello => 'world'}},
318
    xml  => {text => '<hello>world</hello>'}
319
  );
320

            
321
The best possible representation will be automatically selected from the
322
C<Accept> request header, C<format> stash value or C<format> GET/POST
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
323
parameter and stored in the C<format> stash value. To change MIME type
324
mappings for the C<Accept> request header or the C<Content-Type> response
325
header you can use L<Mojolicious/"types">.
copy gitweblite soruce code
root authored on 2012-11-23
326

            
327
  $self->respond_to(
328
    json => {json => {hello => 'world'}},
329
    html => sub {
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
330
      $self->content_for(head => '<meta name="author" content="sri">');
copy gitweblite soruce code
root authored on 2012-11-23
331
      $self->render(template => 'hello', message => 'world')
332
    }
333
  );
334

            
335
Callbacks can be used for representations that are too complex to fit into a
336
single render call.
337

            
338
  # /hello (Accept: application/json) -> "json"
339
  # /hello (Accept: text/html)        -> "html"
340
  # /hello (Accept: image/png)        -> "any"
341
  # /hello.json                       -> "json"
342
  # /hello.html                       -> "html"
343
  # /hello.png                        -> "any"
344
  # /hello?format=json                -> "json"
345
  # /hello?format=html                -> "html"
346
  # /hello?format=png                 -> "any"
347
  $self->respond_to(
348
    json => {json => {hello => 'world'}},
349
    html => {template => 'hello', message => 'world'},
350
    any  => {text => '', status => 204}
351
  );
352

            
353
And if no viable representation could be found, the C<any> fallback will be
354
used or an empty C<204> response rendered automatically.
355

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
356
=head2 Rendering C<exception> and C<not_found> pages
357

            
358
By now you've probably already encountered the built-in 404 (Not Found) and
359
500 (Server Error) pages, that get rendered automatically when you make a
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
360
mistake. Especially during development they can be a great help, you can
361
render them manually with the methods
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
362
L<Mojolicious::Controller/"render_exception"> and
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
363
L<Mojolicious::Controller/"render_not_found">.
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
364

            
365
  use Mojolicious::Lite;
366
  use Scalar::Util 'looks_like_number';
367

            
368
  get '/divide/:dividend/by/:divisor' => sub {
369
    my $self = shift;
370
    my ($dividend, $divisor) = $self->param(['dividend', 'divisor']);
371

            
372
    # 404
373
    return $self->render_not_found
374
      unless looks_like_number $dividend && looks_like_number $divisor;
375

            
376
    # 500
377
    return $self->render_exception('Division by zero!') if $divisor == 0;
378

            
379
    # 200
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
380
    $self->render(text => $dividend / $divisor);
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
381
  };
382

            
383
  app->start;
384

            
385
You can also change the templates of those pages, since you most likely want
386
to show your users something more closely related to your application in
387
production. The renderer will always try to find C<exception.$mode.$format.*>
388
or C<not_found.$mode.$format.*> before falling back to the built-in default
389
templates.
390

            
391
  @@ exception.production.html.ep
392
  <!DOCTYPE html>
393
  <html>
394
    <head><title>Server error</title></head>
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
395
    <body>
396
      <h1>Exception</h1>
397
      <p><%= $exception->message %></p>
398
      <h1>Stash</h1>
399
      <pre><%= dumper $snapshot %></pre>
400
    </body>
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
401
  </html>
402

            
copy gitweblite soruce code
root authored on 2012-11-23
403
=head2 Helpers
404

            
405
Helpers are little functions you can use in templates and controller code.
406

            
407
  %= dumper [1, 2, 3]
408

            
409
  my $serialized = $self->dumper([1, 2, 3]);
410

            
411
The helper L<Mojolicious::Plugin::DefaultHelpers/"dumper"> for example will
412
use L<Data::Dumper> to serialize whatever data structure you pass it, this can
413
be very useful for debugging. We differentiate between C<default helpers>
414
which are more general purpose like C<dumper> and C<tag helpers>, which are
415
template specific and mostly used to generate C<HTML> tags.
416

            
417
  %= javascript '/script.js'
418

            
419
  %= javascript begin
420
    var a = 'b';
421
  % end
422

            
423
A list of all built-in helpers can be found in
424
L<Mojolicious::Plugin::DefaultHelpers> and L<Mojolicious::Plugin::TagHelpers>.
425

            
426
=head2 Layouts
427

            
428
Most of the time when using C<ep> templates you will want to wrap your
429
generated content in a HTML skeleton, thanks to layouts that's absolutely
430
trivial.
431

            
432
  @@ foo/bar.html.ep
433
  % layout 'mylayout';
434
  Hello World!
435

            
436
  @@ layouts/mylayout.html.ep
437
  <!DOCTYPE html>
438
  <html>
439
    <head><title>MyApp</title></head>
440
    <body><%= content %></body>
441
  </html>
442

            
443
You just select the right layout template with the helper
444
L<Mojolicious::Plugin::DefaultHelpers/"layout"> and place the result of the
445
current template with the helper
446
L<Mojolicious::Plugin::DefaultHelpers/"content">. You can also pass along
447
normal stash values to the C<layout> helper.
448

            
449
  @@ foo/bar.html.ep
450
  % layout 'mylayout', title => 'Hi there';
451
  Hello World!
452

            
453
  @@ layouts/mylayout.html.ep
454
  <!DOCTYPE html>
455
  <html>
456
    <head><title><%= $title %></title></head>
457
    <body><%= content %></body>
458
  </html>
459

            
460
Instead of the C<layout> helper you could also just use the C<layout> stash
461
value, or call L<Mojolicious::Controller/"render"> with the C<layout>
462
argument.
463

            
464
  $self->render(template => 'mytemplate', layout => 'mylayout');
465

            
466
To set a C<layout> stash value application wide you can use
467
L<Mojolicious/"defaults">.
468

            
469
  # Application
470
  package MyApp;
471
  use Mojo::Base 'Mojolicious';
472

            
473
  sub startup {
474
    my $self = shift;
475

            
476
    # Default layout
477
    $self->defaults(layout => 'mylayout');
478
  }
479

            
480
  1;
481

            
482
=head2 Including partial templates
483

            
484
Like most helpers L<Mojolicious::Plugin::DefaultHelpers/"include"> is just a
485
shortcut to make your life a little easier.
486

            
487
  @@ foo/bar.html.ep
488
  <!DOCTYPE html>
489
  <html>
490
    %= include 'header'
491
    <body>Bar</body>
492
  </html>
493

            
494
  @@ header.html.ep
495
  <head><title>Howdy</title></head>
496

            
497
Instead of C<include> you could also just call
498
L<Mojolicious::Controller/"render"> with the C<partial> argument.
499

            
500
  @@ foo/bar.html.ep
501
  <!DOCTYPE html>
502
  <html>
503
    %= $self->render('header', partial => 1)
504
    <body>Bar</body>
505
  </html>
506

            
507
  @@ header.html.ep
508
  <head><title>Howdy</title></head>
509

            
510
But there is one small difference between the two, if you pass stash values to
511
C<include>, they will get localized automatically and are only available in
512
the partial template.
513

            
514
  @@ foo/bar.html.ep
515
  <!DOCTYPE html>
516
  <html>
517
    %= include 'header', title => 'Hello'
518
    <body>Bar</body>
519
  </html>
520

            
521
  @@ header.html.ep
522
  <head><title><%= $title %></title></head>
523

            
524
=head2 Reusable template blocks
525

            
526
It's never fun to repeat yourself, that's why you can build reusable template
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
527
blocks in C<ep> that work very similar to normal Perl functions.
copy gitweblite soruce code
root authored on 2012-11-23
528

            
529
  @@ welcome.html.ep
530
  <% my $block = begin %>
531
    <% my $name = shift; %>
532
    Hello <%= $name %>.
533
  <% end %>
534
  <%= $block->('Sebastian') %>
535
  <%= $block->('Sara') %>
536

            
537
Blocks are always delimited by the C<begin> and C<end> keywords.
538

            
539
  @@ welcome.html.ep
540
  % my $block = begin
541
    % my $name = shift;
542
    Hello <%= $name %>.
543
  % end
544
  % for (1 .. 10) {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
545
    %== $block->('Sebastian')
copy gitweblite soruce code
root authored on 2012-11-23
546
  % }
547

            
548
A naive translation to Perl code could look like this.
549

            
550
  @@ welcome.html.pl
551
  my $output = '';
552
  my $block  = sub {
553
    my $name   = shift;
554
    my $output = '';
555
    $output .= 'Hello ';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
556
    $output .= xml_escape scalar $name;
copy gitweblite soruce code
root authored on 2012-11-23
557
    $output .= '.';
558
    return Mojo::ByteStream->new($output);
559
  }
560
  for (1 .. 10) {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
561
    $output .= scalar $block->('Sebastian');
copy gitweblite soruce code
root authored on 2012-11-23
562
  }
563
  return $output;
564

            
565
=head2 Content blocks
566

            
567
Blocks and the helper L<Mojolicious::Plugin::DefaultHelpers/"content_for">
568
can also be used to pass whole sections of the template to the layout.
569

            
570
  @@ foo/bar.html.ep
571
  % layout 'mylayout';
572
  % content_for header => begin
573
    <meta http-equiv="Content-Type" content="text/html">
574
  % end
575
  <div>Hello World!</div>
576
  % content_for header => begin
577
    <meta http-equiv="Pragma" content="no-cache">
578
  % end
579

            
580
  @@ layouts/mylayout.html.ep
581
  <!DOCTYPE html>
582
  <html>
583
    <head><%= content_for 'header' %></head>
584
    <body><%= content %></body>
585
  </html>
586

            
587
=head2 Template inheritance
588

            
589
Inheritance takes the layout concept above one step further, the helpers
590
L<Mojolicious::Plugin::DefaultHelpers/"content"> and
591
L<Mojolicious::Plugin::DefaultHelpers/"extends"> allow you to build a skeleton
592
template with named blocks that child templates can override.
593

            
594
  @@ first.html.ep
595
  <!DOCTYPE html>
596
  <html>
597
    <head><title>Hello</title></head>
598
    <body>
599
      %= content header => begin
600
        Default header
601
      % end
602
      <div>Hello World!</div>
603
      %= content footer => begin
604
        Default footer
605
      % end
606
    </body>
607
  </html>
608

            
609
  @@ second.html.ep
610
  % extends 'first';
611
  % content header => begin
612
    New header
613
  % end
614

            
615
This chain could go on and on to allow a very high level of template reuse.
616

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
617
=head2 Form validation
618

            
619
You can use L<Mojolicious::Controller/"validation"> to validate GET/POST
620
parameters submitted to your application. All unknown fields will be ignored
621
by default, so you have to decide which should be required or optional before
622
you can perform checks on their values. Every check is performed right away,
623
so you can use the results immediately to build more advanced validation logic
624
with methods like L<Mojolicious::Validator::Validation/"is_valid">.
625

            
626
  use Mojolicious::Lite;
627

            
628
  get '/' => sub {
629
    my $self = shift;
630

            
631
    # Check if parameters have been submitted
632
    my $validation = $self->validation;
633
    return $self->render unless $validation->has_data;
634

            
635
    # Validate parameters ("pass_again" depends on "pass")
636
    $validation->required('user')->size(1, 20)->like(qr/^[e-t]+$/);
637
    $validation->required('pass_again')->equal_to('pass')
638
      if $validation->optional('pass')->size(7, 500)->is_valid;
639

            
640
    # Render confirmation if validation was successful
641
    $self->render('thanks') unless $validation->has_error;
642
  } => 'index';
643

            
644
  app->start;
645
  __DATA__
646

            
647
  @@ index.html.ep
648
  <!DOCTYPE html>
649
  <html>
650
    <head>
651
      %= stylesheet begin
652
        label.field-with-error { color: #dd7e5e }
653
        input.field-with-error { background-color: #fd9e7e }
654
      % end
655
    </head>
656
    <body>
657
      %= form_for index => begin
658
        %= label_for user => 'Username (required, 1-20 characters, only e-t)'
659
        <br>
660
        %= text_field 'user'
661
        %= submit_button
662
        <br>
663
        %= label_for pass => 'Password (optional, 7-500 characters)'
664
        <br>
665
        %= password_field 'pass'
666
        <br>
667
        %= label_for pass_again => 'Password again (equal to the value above)'
668
        <br>
669
        %= password_field 'pass_again'
670
      % end
671
    </body>
672
  </html>
673

            
674
  @@ thanks.html.ep
675
  <!DOCTYPE html>
676
  <html><body>Thank you <%= validation->param('user') %>.</body></html>
677

            
678
Form elements generated with tag helpers from
679
L<Mojolicious::Plugin::TagHelpers> will automatically remember their previous
680
values and add the class C<field-with-error> for fields that failed validation
681
to make styling with CSS easier.
682

            
683
  <label class="field-with-error" for="user">
684
    Username (required, only characters e-t)
685
  </label>
686
  <input class="field-with-error" type="text" name="user" value="sri" />
687

            
688
For a full list of available checks see also
689
L<Mojolicious::Validator/"CHECKS">.
690

            
691
=head2 Adding form validation checks
692

            
693
Validation checks can be registered with L<Mojolicious::Validator/"add_check">
694
and return a false value if they were successful. A true value may be used to
695
pass along additional information which can then be retrieved with
696
L<Mojolicious::Validator::Validation/"error">.
697

            
698
  use Mojolicious::Lite;
699

            
700
  # Add "range" check
701
  app->validator->add_check(range => sub {
702
    my ($validation, $name, $value, $min, $max) = @_;
703
    return $value < $min || $value > $max;
704
  });
705

            
706
  get '/' => 'form';
707

            
708
  post '/test' => sub {
709
    my $self = shift;
710

            
711
    # Validate parameters with custom check
712
    my $validation = $self->validation;
713
    $validation->required('number')->range(3, 23);
714

            
715
    # Render form again if validation failed
716
    return $self->render('form') if $validation->has_error;
717

            
718
    # Prevent double submit with redirect
719
    $self->flash(number => $validation->param('number'));
720
    $self->redirect_to('form');
721
  };
722

            
723
  app->start;
724
  __DATA__
725

            
726
  @@ form.html.ep
727
  <!DOCTYPE html>
728
  <html>
729
    <body>
730
      % if (my $number = flash 'number') {
731
        <p>Thanks, the number <%= $number %> was valid.</p>
732
      % }
733
      %= form_for test => begin
734
        % if (my $err = validation->error('number')) {
735
          <p>
736
            %= 'Value is required.' if $err->[0] eq 'required'
737
            %= 'Value needs to be between 3 and 23.' if $err->[0] eq 'range'
738
          </p>
739
        % }
740
        %= text_field 'number'
741
        %= submit_button
742
      % end
743
    </html>
744
  </html>
745

            
copy gitweblite soruce code
root authored on 2012-11-23
746
=head2 Adding helpers
747

            
748
Adding and redefining helpers is very easy, you can use them to do pretty much
749
everything.
750

            
751
  use Mojolicious::Lite;
752

            
753
  helper debug => sub {
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
754
    my ($self, $str) = @_;
755
    $self->app->log->debug($str);
copy gitweblite soruce code
root authored on 2012-11-23
756
  };
757

            
758
  get '/' => sub {
759
    my $self = shift;
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
760
    $self->debug('Hello from an action!');
copy gitweblite soruce code
root authored on 2012-11-23
761
  } => 'index';
762

            
763
  app->start;
764
  __DATA__
765

            
766
  @@ index.html.ep
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
767
  % debug 'Hello from a template!';
copy gitweblite soruce code
root authored on 2012-11-23
768

            
769
Helpers can also accept template blocks as last argument, this for example
770
allows very pleasant to use tag helpers and filters.
771

            
772
  use Mojolicious::Lite;
773
  use Mojo::ByteStream;
774

            
775
  helper trim_newline => sub {
776
    my ($self, $block) = @_;
777
    my $result = $block->();
778
    $result =~ s/\n//g;
779
    return Mojo::ByteStream->new($result);
780
  };
781

            
782
  get '/' => 'index';
783

            
784
  app->start;
785
  __DATA__
786

            
787
  @@ index.html.ep
788
  %= trim_newline begin
789
    Some text.
790
    %= 1 + 1
791
    More text.
792
  % end
793

            
794
Wrapping the helper result into a L<Mojo::ByteStream> object can prevent
795
accidental double escaping.
796

            
797
=head2 Helper plugins
798

            
799
Some helpers might be useful enough for you to share them between multiple
800
applications, plugins make that very simple.
801

            
802
  package Mojolicious::Plugin::DebugHelper;
803
  use Mojo::Base 'Mojolicious::Plugin';
804

            
805
  sub register {
806
    my ($self, $app) = @_;
807
    $app->helper(debug => sub {
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
808
      my ($self, $str) = @_;
809
      $self->app->log->debug($str);
copy gitweblite soruce code
root authored on 2012-11-23
810
    });
811
  }
812

            
813
  1;
814

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
815
The C<register> method will be called when you load the plugin and to add your
816
helper to the application you can use L<Mojolicious/"helper">.
copy gitweblite soruce code
root authored on 2012-11-23
817

            
818
  use Mojolicious::Lite;
819

            
820
  plugin 'DebugHelper';
821

            
822
  get '/' => sub {
823
    my $self = shift;
824
    $self->debug('It works.');
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
825
    $self->render(text => 'Hello.');
copy gitweblite soruce code
root authored on 2012-11-23
826
  };
827

            
828
  app->start;
829

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
830
A skeleton for a full CPAN compatible plugin distribution can be automatically
831
generated.
copy gitweblite soruce code
root authored on 2012-11-23
832

            
833
  $ mojo generate plugin DebugHelper
834

            
835
And if you have a C<PAUSE> account (which can be requested at
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
836
L<http://pause.perl.org>), you are only a few commands away from releasing it
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
837
to CPAN.
copy gitweblite soruce code
root authored on 2012-11-23
838

            
839
  $ perl Makefile.PL
840
  $ make test
841
  $ make manifest
842
  $ make dist
843
  $ mojo cpanify -u USER -p PASS Mojolicious-Plugin-DebugHelper-0.01.tar.gz
844

            
845
=head2 Bundling assets with plugins
846

            
847
Assets such as templates and static files can be easily bundled with your
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
848
plugins, even if you plan to release them to CPAN.
copy gitweblite soruce code
root authored on 2012-11-23
849

            
850
  $ mojo generate plugin AlertAssets
851
  $ mkdir AlertAssets/lib/Mojolicious/Plugin/AlertAssets
852
  $ cd AlertAssets/lib/Mojolicious/Plugin/AlertAssets
853
  $ mkdir public
854
  $ echo 'alert("Hello World!");' > public/alertassets.js
855
  $ mkdir templates
856
  $ echo '%= javascript "/alertassets.js"' > templates/alertassets.html.ep
857

            
858
Just append their respective directories to the list of search paths when
859
C<register> is called.
860

            
861
  package Mojolicious::Plugin::AlertAssets;
862
  use Mojo::Base 'Mojolicious::Plugin';
863

            
864
  use File::Basename 'dirname';
865
  use File::Spec::Functions 'catdir';
866

            
867
  sub register {
868
    my ($self, $app) = @_;
869

            
870
    # Append "templates" and "public" directories
871
    my $base = catdir(dirname(__FILE__), 'AlertAssets');
872
    push @{$app->renderer->paths}, catdir($base, 'templates');
873
    push @{$app->static->paths},   catdir($base, 'public');
874
  }
875

            
876
  1;
877

            
878
Both will work just like normal C<templates> and C<public> directories once
879
you've installed and loaded the plugin, with slightly lower precedence.
880

            
881
  use Mojolicious::Lite;
882

            
883
  plugin 'AlertAssets';
884

            
885
  get '/alert_me';
886

            
887
  app->start;
888
  __DATA__
889

            
890
  @@ alert_me.html.ep
891
  <!DOCTYPE html>
892
  <html>
893
    <head>
894
      <title>Alert me!</title>
895
      %= include 'alertassets'
896
    </head>
897
    <body>You've been alerted.</body>
898
  </html>
899

            
900
And it works just the same for assets bundled in the C<DATA> section of your
901
plugin.
902

            
903
  package Mojolicious::Plugin::AlertAssets;
904
  use Mojo::Base 'Mojolicious::Plugin';
905

            
906
  sub register {
907
    my ($self, $app) = @_;
908

            
909
    # Append class
910
    push @{$app->renderer->classes}, __PACKAGE__;
911
    push @{$app->static->classes},   __PACKAGE__;
912
  }
913

            
914
  1;
915
  __DATA__
916

            
917
  @@ alertassets.js
918
  alert("Hello World!");
919

            
920
  @@ alertassets.html.ep
921
  %= javascript "/alertassets.js"
922

            
923
=head1 ADVANCED
924

            
925
Less commonly used and more powerful features.
926

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
927
=head2 Rendering static files
copy gitweblite soruce code
root authored on 2012-11-23
928

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
929
If automatic rendering of static files is not enough, you can also render them
930
manually from your C<DATA> sections and C<public> directories with
931
L<Mojolicious::Controller/"render_static">.
copy gitweblite soruce code
root authored on 2012-11-23
932

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
933
  $self->res->headers->content_disposition('attachment; filename=bar.png;');
934
  $self->render_static('foo/bar.png');
copy gitweblite soruce code
root authored on 2012-11-23
935

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
936
=head2 Custom responses
copy gitweblite soruce code
root authored on 2012-11-23
937

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
938
For entirely custom responses to, for example, stream content directly from
939
files, you can use L<Mojolicious::Controller/"rendered"> to tell the renderer
940
that a response has been generated.
copy gitweblite soruce code
root authored on 2012-11-23
941

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
942
  $self->res->headers->content_type('text/plain');
943
  $self->res->content->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
944
  $self->rendered(200);
copy gitweblite soruce code
root authored on 2012-11-23
945

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
946
=head2 Post-processing dynamic content
947

            
948
While post-processing tasks are generally very easy with the C<after_dispatch>
949
hook, for content generated by the renderer it is a lot more efficient to use
950
C<after_render>.
951

            
952
  use Mojolicious::Lite;
953
  use IO::Compress::Gzip 'gzip';
954

            
955
  hook after_render => sub {
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
956
    my ($c, $output, $format) = @_;
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
957

            
958
    # Check if "gzip => 1" has been set in the stash
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
959
    return unless $c->stash->{gzip};
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
960

            
961
    # Check if user agent accepts GZip compression
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
962
    return unless ($c->req->headers->accept_encoding // '') =~ /gzip/i;
963
    $c->res->headers->append(Vary => 'Accept-Encoding');
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
964

            
965
    # Compress content with GZip
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
966
    $c->res->headers->content_encoding('gzip');
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
967
    gzip $output, \my $compressed;
968
    $$output = $compressed;
969
  };
970

            
971
  get '/' => {template => 'hello', title => 'Hello', gzip => 1};
972

            
973
  app->start;
974
  __DATA__
975

            
976
  @@ hello.html.ep
977
  <!DOCTYPE html>
978
  <html>
979
    <head><title><%= title %></title></head>
980
    <body>Compressed content.</body>
981
  </html>
982

            
copy gitweblite soruce code
root authored on 2012-11-23
983
=head2 Chunked transfer encoding
984

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
985
For very dynamic content you might not know the response content length in
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
986
advance, that's where the C<chunked> transfer encoding and
987
L<Mojolicious::Controller/"write_chunk"> come in handy. A common use would be
988
to send the C<head> section of an HTML document to the browser in advance and
989
speed up preloading of referenced images and stylesheets.
copy gitweblite soruce code
root authored on 2012-11-23
990

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
991
  $self->write_chunk('<html><head><title>Example</title></head>' => sub {
copy gitweblite soruce code
root authored on 2012-11-23
992
    my $self = shift;
993
    $self->finish('<body>Example</body></html>');
994
  });
995

            
996
The optional drain callback ensures that all previous chunks have been
997
written before processing continues. An empty chunk or call to
998
L<Mojolicious::Controller/"finish"> marks the end of the stream.
999

            
1000
  29
1001
  <html><head><title>Example</title></head>
1002
  1b
1003
  <body>Example</body></html>
1004
  0
1005

            
1006
Especially in combination with long inactivity timeouts this can be very
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1007
useful for Comet (long polling). Due to limitations in some web servers this
1008
might not work perfectly in all deployment environments.
copy gitweblite soruce code
root authored on 2012-11-23
1009

            
1010
=head2 Encoding
1011

            
1012
Templates stored in files are expected to be C<UTF-8> by default, but that can
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
1013
be easily changed with L<Mojolicious::Renderer/"encoding">.
copy gitweblite soruce code
root authored on 2012-11-23
1014

            
1015
  # Application
1016
  package MyApp;
1017
  use Mojo::Base 'Mojolicious';
1018

            
1019
  sub startup {
1020
    my $self = shift;
1021

            
1022
    # Different encoding
1023
    $self->renderer->encoding('koi8-r');
1024
  }
1025

            
1026
  1;
1027

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1028
All templates from the C<DATA> section are bound to the encoding of the Perl
1029
script.
copy gitweblite soruce code
root authored on 2012-11-23
1030

            
1031
  use Mojolicious::Lite;
1032

            
1033
  get '/heart';
1034

            
1035
  app->start;
1036

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1037
  __DATA__
copy gitweblite soruce code
root authored on 2012-11-23
1038
  @@ heart.html.ep
1039
  I ♥ Mojolicious!
1040

            
1041
=head2 Base64 encoded DATA files
1042

            
1043
Base64 encoded static files such as images can be easily stored in the C<DATA>
1044
section of your application, similar to templates.
1045

            
1046
  @@ favicon.ico (base64)
1047
  ...base64 encoded image...
1048

            
1049
=head2 Inflating DATA templates
1050

            
1051
Templates stored in files get preferred over files from the C<DATA> section,
1052
this allows you to include a default set of templates in your application that
1053
the user can later customize. The C<inflate> command will write all templates
1054
and static files from the C<DATA> section into actual files in the
1055
C<templates> and C<public> directories.
1056

            
1057
  $ ./myapp.pl inflate
1058

            
1059
=head2 Customizing the template syntax
1060

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1061
You can easily change the whole template syntax by loading
1062
L<Mojolicious::Plugin::EPRenderer> with a custom configuration.
copy gitweblite soruce code
root authored on 2012-11-23
1063

            
1064
  use Mojolicious::Lite;
1065

            
1066
  plugin EPRenderer => {
1067
    name     => 'mustache',
1068
    template => {
1069
      tag_start => '{{',
1070
      tag_end   => '}}'
1071
    }
1072
  };
1073

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1074
  get '/:name' => {name => 'Anonymous'} => 'index';
copy gitweblite soruce code
root authored on 2012-11-23
1075

            
1076
  app->start;
1077
  __DATA__
1078

            
1079
  @@ index.html.mustache
1080
  Hello {{= $name }}.
1081

            
1082
L<Mojo::Template> contains the whole list of available options.
1083

            
1084
=head2 Adding your favorite template system
1085

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1086
Maybe you would prefer a different template system than C<ep>, and there is
1087
not already a plugin on CPAN for your favorite one, all you have to do is add
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
1088
a new C<handler> with L<Mojolicious::Renderer/"add_handler"> when C<register>
1089
is called.
copy gitweblite soruce code
root authored on 2012-11-23
1090

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1091
  package Mojolicious::Plugin::MyRenderer;
1092
  use Mojo::Base 'Mojolicious::Plugin';
1093

            
1094
  sub register {
1095
    my ($self, $app) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
1096

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1097
    # Add "mine" handler
1098
    $app->renderer->add_handler(mine => sub {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1099
      my ($renderer, $c, $output, $options) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
1100

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1101
      # Check for one-time use inline template
copy gitweblite soruce code
root authored on 2012-11-23
1102
      my $inline = $options->{inline};
1103

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1104
      # Check for absolute template path
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1105
      my $path = $renderer->template_path($options);
copy gitweblite soruce code
root authored on 2012-11-23
1106

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1107
      # Check for appropriate template in DATA section
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1108
      my $data = $renderer->get_data_template($options);
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1109

            
copy gitweblite soruce code
root authored on 2012-11-23
1110
      # This part is up to you and your template system :)
1111
      ...
1112

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1113
      # Just die if an error occurs
1114
      die 'Something went wrong';
copy gitweblite soruce code
root authored on 2012-11-23
1115

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1116
      # Or pass the rendered result back to the renderer
1117
      $$output = 'Hello World!';
1118

            
1119
      # And return true if something has been rendered or false otherwise
copy gitweblite soruce code
root authored on 2012-11-23
1120
      return 1;
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1121
    });
1122
  }
copy gitweblite soruce code
root authored on 2012-11-23
1123

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1124
  1;
copy gitweblite soruce code
root authored on 2012-11-23
1125

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1126
Since most template systems don't support templates in the C<DATA> section,
1127
the renderer provides methods to help you with that.
1128

            
1129
  use Mojolicious::Lite;
1130

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1131
  plugin 'MyRenderer';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1132

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1133
  get '/' => 'index';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1134

            
1135
  app->start;
1136
  __DATA__
1137

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1138
  @@ index.html.mine
1139
  ...
copy gitweblite soruce code
root authored on 2012-11-23
1140

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
1141
=head2 Adding a handler to generate binary data
1142

            
1143
By default the renderer assumes that every C<handler> generates characters
1144
that need to be automatically encoded, but this can be be easily disabled if
1145
you're generating bytes instead.
1146

            
1147
  use Mojolicious::Lite;
1148
  use Mango::BSON ':bson';
1149

            
1150
  # Add "bson" handler
1151
  app->renderer->add_handler(bson => sub {
1152
    my ($renderer, $c, $output, $options) = @_;
1153

            
1154
    # Disable automatic encoding
1155
    delete $options->{encoding};
1156

            
1157
    # Encode BSON data from stash value
1158
    $$output = bson_encode delete $c->stash->{bson};
1159

            
1160
    return 1;
1161
  });
1162

            
1163
  get '/' => {bson => {i => '♥ mojolicious'}, handler => 'bson'};
1164

            
1165
  app->start;
1166

            
copy gitweblite soruce code
root authored on 2012-11-23
1167
=head1 MORE
1168

            
1169
You can continue with L<Mojolicious::Guides> now or take a look at the
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
1170
L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot
copy gitweblite soruce code
root authored on 2012-11-23
1171
more documentation and examples by many different authors.
1172

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
1173
=head1 SUPPORT
1174

            
1175
If you have any questions the documentation might not yet answer, don't
1176
hesitate to ask on the
1177
L<mailing-list|http://groups.google.com/group/mojolicious> or the official IRC
1178
channel C<#mojo> on C<irc.perl.org>.
1179

            
copy gitweblite soruce code
root authored on 2012-11-23
1180
=cut