Newer Older
215 lines | 5.608kb
copy gitweblite soruce code
root authored on 2012-11-23
1
package Mojolicious::Plugin::PODRenderer;
2
use Mojo::Base 'Mojolicious::Plugin';
3

            
4
use Mojo::Asset::File;
5
use Mojo::ByteStream 'b';
6
use Mojo::DOM;
7
use Mojo::Util 'url_escape';
8
BEGIN {eval {require Pod::Simple::HTML; import Pod::Simple::HTML}}
9
BEGIN {eval {require Pod::Simple::Search; import Pod::Simple::Search}}
10

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
11
# Paths to search
copy gitweblite soruce code
root authored on 2012-11-23
12
my @PATHS = map { $_, "$_/pods" } @INC;
13

            
14
sub register {
15
  my ($self, $app, $conf) = @_;
16

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
17
  my $preprocess = $conf->{preprocess} || 'ep';
copy gitweblite soruce code
root authored on 2012-11-23
18
  $app->renderer->add_handler(
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
19
    $conf->{name} || 'pod' => sub {
20
      my ($renderer, $c, $output, $options) = @_;
21

            
22
      # Preprocess and render
23
      my $handler = $renderer->handlers->{$preprocess};
24
      return undef unless $handler->($renderer, $c, $output, $options);
25
      $$output = _pod_to_html($$output);
26
      return 1;
copy gitweblite soruce code
root authored on 2012-11-23
27
    }
28
  );
29

            
30
  $app->helper(pod_to_html => sub { shift; b(_pod_to_html(@_)) });
31

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
32
  # Perldoc browser
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
33
  return if $conf->{no_perldoc};
34
  return $app->routes->any(
35
    '/perldoc/*module' => {module => 'Mojolicious/Guides'} => \&_perldoc);
36
}
copy gitweblite soruce code
root authored on 2012-11-23
37

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
38
sub _perldoc {
39
  my $self = shift;
40

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
41
  # Find module or redirect to CPAN
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
42
  my $module = $self->param('module');
43
  $module =~ s!/!::!g;
44
  my $path = Pod::Simple::Search->new->find($module, @PATHS);
45
  return $self->redirect_to("http://metacpan.org/module/$module")
46
    unless $path && -r $path;
47

            
48
  # Turn POD into HTML
49
  open my $file, '<', $path;
50
  my $html = _pod_to_html(join '', <$file>);
51

            
52
  # Rewrite links
53
  my $dom     = Mojo::DOM->new("$html");
54
  my $perldoc = $self->url_for('/perldoc/');
55
  $dom->find('a[href]')->each(
56
    sub {
57
      my $attrs = shift->attrs;
58
      $attrs->{href} =~ s!%3A%3A!/!gi
59
        if $attrs->{href} =~ s!^http://search\.cpan\.org/perldoc\?!$perldoc!;
60
    }
61
  );
62

            
63
  # Rewrite code blocks for syntax highlighting
64
  $dom->find('pre')->each(
65
    sub {
66
      my $e = shift;
67
      return if $e->all_text =~ /^\s*\$\s+/m;
68
      my $attrs = $e->attrs;
69
      my $class = $attrs->{class};
70
      $attrs->{class} = defined $class ? "$class prettyprint" : 'prettyprint';
71
    }
72
  );
copy gitweblite soruce code
root authored on 2012-11-23
73

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
74
  # Rewrite headers
75
  my $url = $self->req->url->clone;
76
  my (%anchors, @parts);
77
  $dom->find('h1, h2, h3')->each(
78
    sub {
79
      my $e = shift;
80

            
81
      # Anchor and text
82
      my $name = my $text = $e->all_text;
83
      $name =~ s/\s+/_/g;
84
      $name =~ s/\W//g;
85
      my $anchor = $name;
86
      my $i      = 1;
87
      $anchor = $name . $i++ while $anchors{$anchor}++;
88

            
89
      # Rewrite
90
      push @parts, [] if $e->type eq 'h1' || !@parts;
91
      push @{$parts[-1]}, $text, $url->fragment($anchor)->to_abs;
92
      $e->replace_content(
93
        $self->link_to(
94
          $text => $url->fragment('toc')->to_abs,
95
          class => 'mojoscroll',
96
          id    => $anchor
97
        )
copy gitweblite soruce code
root authored on 2012-11-23
98
      );
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
99
    }
100
  );
copy gitweblite soruce code
root authored on 2012-11-23
101

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
102
  # Try to find a title
103
  my $title = 'Perldoc';
104
  $dom->find('h1 + p')->first(sub { $title = shift->text });
copy gitweblite soruce code
root authored on 2012-11-23
105

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
106
  # Combine everything to a proper response
107
  $self->content_for(perldoc => "$dom");
108
  my $template = $self->app->renderer->_bundled('perldoc');
109
  $self->render(inline => $template, title => $title, parts => \@parts);
110
  $self->res->headers->content_type('text/html;charset="UTF-8"');
copy gitweblite soruce code
root authored on 2012-11-23
111
}
112

            
113
sub _pod_to_html {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
114
  return undef unless defined(my $pod = shift);
copy gitweblite soruce code
root authored on 2012-11-23
115

            
116
  # Block
117
  $pod = $pod->() if ref $pod eq 'CODE';
118

            
119
  my $parser = Pod::Simple::HTML->new;
120
  $parser->force_title('');
121
  $parser->html_header_before_title('');
122
  $parser->html_header_after_title('');
123
  $parser->html_footer('');
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
124
  $parser->output_string(\(my $output));
125
  return $@ unless eval { $parser->parse_string_document("$pod"); 1 };
copy gitweblite soruce code
root authored on 2012-11-23
126

            
127
  # Filter
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
128
  $output =~ s!<a name='___top' class='dummyTopAnchor'\s*?></a>\n!!g;
129
  $output =~ s!<a class='u'.*?name=".*?"\s*>(.*?)</a>!$1!sg;
copy gitweblite soruce code
root authored on 2012-11-23
130

            
131
  return $output;
132
}
133

            
134
1;
135

            
136
=head1 NAME
137

            
138
Mojolicious::Plugin::PODRenderer - POD renderer plugin
139

            
140
=head1 SYNOPSIS
141

            
142
  # Mojolicious
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
143
  my $route = $self->plugin('PODRenderer');
144
  my $route = $self->plugin(PODRenderer => {name => 'foo'});
145
  my $route = $self->plugin(PODRenderer => {preprocess => 'epl'});
copy gitweblite soruce code
root authored on 2012-11-23
146

            
147
  # Mojolicious::Lite
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
148
  my $route = plugin 'PODRenderer';
149
  my $route = plugin PODRenderer => {name => 'foo'};
150
  my $route = plugin PODRenderer => {preprocess => 'epl'};
151

            
152
  # foo.html.ep
copy gitweblite soruce code
root authored on 2012-11-23
153
  %= pod_to_html "=head1 TEST\n\nC<123>"
154

            
155
=head1 DESCRIPTION
156

            
157
L<Mojolicious::Plugin::PODRenderer> is a renderer for true Perl hackers, rawr!
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
158

            
159
The code of this plugin is a good example for learning to build new plugins,
160
you're welcome to fork it.
copy gitweblite soruce code
root authored on 2012-11-23
161

            
162
=head1 OPTIONS
163

            
164
L<Mojolicious::Plugin::PODRenderer> supports the following options.
165

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
166
=head2 name
copy gitweblite soruce code
root authored on 2012-11-23
167

            
168
  # Mojolicious::Lite
169
  plugin PODRenderer => {name => 'foo'};
170

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
171
Handler name, defaults to C<pod>.
copy gitweblite soruce code
root authored on 2012-11-23
172

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
173
=head2 no_perldoc
copy gitweblite soruce code
root authored on 2012-11-23
174

            
175
  # Mojolicious::Lite
176
  plugin PODRenderer => {no_perldoc => 1};
177

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
178
Disable L<Mojolicious::Guides> documentation browser that will otherwise be
179
available under C</perldoc>.
copy gitweblite soruce code
root authored on 2012-11-23
180

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
181
=head2 preprocess
copy gitweblite soruce code
root authored on 2012-11-23
182

            
183
  # Mojolicious::Lite
184
  plugin PODRenderer => {preprocess => 'epl'};
185

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
186
Name of handler used to preprocess POD, defaults to C<ep>.
copy gitweblite soruce code
root authored on 2012-11-23
187

            
188
=head1 HELPERS
189

            
190
L<Mojolicious::Plugin::PODRenderer> implements the following helpers.
191

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
192
=head2 pod_to_html
copy gitweblite soruce code
root authored on 2012-11-23
193

            
194
  %= pod_to_html '=head2 lalala'
195
  <%= pod_to_html begin %>=head2 lalala<% end %>
196

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
197
Render POD to HTML without preprocessing.
copy gitweblite soruce code
root authored on 2012-11-23
198

            
199
=head1 METHODS
200

            
201
L<Mojolicious::Plugin::PODRenderer> inherits all methods from
202
L<Mojolicious::Plugin> and implements the following new ones.
203

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
204
=head2 register
copy gitweblite soruce code
root authored on 2012-11-23
205

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
206
  my $route = $plugin->register(Mojolicious->new);
207
  my $route = $plugin->register(Mojolicious->new, {name => 'foo'});
copy gitweblite soruce code
root authored on 2012-11-23
208

            
209
Register renderer in L<Mojolicious> application.
210

            
211
=head1 SEE ALSO
212

            
213
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
214

            
215
=cut