copy gitweblite soruce code
|
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...
|
11 |
# Paths to search |
copy gitweblite soruce code
|
12 |
my @PATHS = map { $_, "$_/pods" } @INC; |
13 | ||
14 |
sub register { |
|
15 |
my ($self, $app, $conf) = @_; |
|
16 | ||
upgraded Mojolicious to v3.7...
|
17 |
my $preprocess = $conf->{preprocess} || 'ep'; |
copy gitweblite soruce code
|
18 |
$app->renderer->add_handler( |
upgraded Mojolicious to v3.7...
|
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
|
27 |
} |
28 |
); |
|
29 | ||
30 |
$app->helper(pod_to_html => sub { shift; b(_pod_to_html(@_)) }); |
|
31 | ||
update Mojolicious and added...
|
32 |
# Perldoc browser |
upgraded Mojolicious to v3.7...
|
33 |
return if $conf->{no_perldoc}; |
34 |
return $app->routes->any( |
|
35 |
'/perldoc/*module' => {module => 'Mojolicious/Guides'} => \&_perldoc); |
|
36 |
} |
|
copy gitweblite soruce code
|
37 | |
upgraded Mojolicious to v3.7...
|
38 |
sub _perldoc { |
39 |
my $self = shift; |
|
40 | ||
update Mojolicious and added...
|
41 |
# Find module or redirect to CPAN |
upgraded Mojolicious to v3.7...
|
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
|
73 | |
upgraded Mojolicious to v3.7...
|
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
|
98 |
); |
upgraded Mojolicious to v3.7...
|
99 |
} |
100 |
); |
|
copy gitweblite soruce code
|
101 | |
upgraded Mojolicious to v3.7...
|
102 |
# Try to find a title |
103 |
my $title = 'Perldoc'; |
|
104 |
$dom->find('h1 + p')->first(sub { $title = shift->text }); |
|
copy gitweblite soruce code
|
105 | |
upgraded Mojolicious to v3.7...
|
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
|
111 |
} |
112 | ||
113 |
sub _pod_to_html { |
|
upgraded Mojolicious to v3.7...
|
114 |
return undef unless defined(my $pod = shift); |
copy gitweblite soruce code
|
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...
|
124 |
$parser->output_string(\(my $output)); |
125 |
return $@ unless eval { $parser->parse_string_document("$pod"); 1 }; |
|
copy gitweblite soruce code
|
126 | |
127 |
# Filter |
|
upgraded Mojolicious to v3.7...
|
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
|
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...
|
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
|
146 | |
147 |
# Mojolicious::Lite |
|
upgraded Mojolicious to v3.7...
|
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
|
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...
|
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
|
161 | |
162 |
=head1 OPTIONS |
|
163 | ||
164 |
L<Mojolicious::Plugin::PODRenderer> supports the following options. |
|
165 | ||
update Mojolicious and added...
|
166 |
=head2 name |
copy gitweblite soruce code
|
167 | |
168 |
# Mojolicious::Lite |
|
169 |
plugin PODRenderer => {name => 'foo'}; |
|
170 | ||
upgraded Mojolicious to v3.7...
|
171 |
Handler name, defaults to C<pod>. |
copy gitweblite soruce code
|
172 | |
update Mojolicious and added...
|
173 |
=head2 no_perldoc |
copy gitweblite soruce code
|
174 | |
175 |
# Mojolicious::Lite |
|
176 |
plugin PODRenderer => {no_perldoc => 1}; |
|
177 | ||
upgraded Mojolicious to v3.7...
|
178 |
Disable L<Mojolicious::Guides> documentation browser that will otherwise be |
179 |
available under C</perldoc>. |
|
copy gitweblite soruce code
|
180 | |
update Mojolicious and added...
|
181 |
=head2 preprocess |
copy gitweblite soruce code
|
182 | |
183 |
# Mojolicious::Lite |
|
184 |
plugin PODRenderer => {preprocess => 'epl'}; |
|
185 | ||
upgraded Mojolicious to v3.7...
|
186 |
Name of handler used to preprocess POD, defaults to C<ep>. |
copy gitweblite soruce code
|
187 | |
188 |
=head1 HELPERS |
|
189 | ||
190 |
L<Mojolicious::Plugin::PODRenderer> implements the following helpers. |
|
191 | ||
update Mojolicious and added...
|
192 |
=head2 pod_to_html |
copy gitweblite soruce code
|
193 | |
194 |
%= pod_to_html '=head2 lalala' |
|
195 |
<%= pod_to_html begin %>=head2 lalala<% end %> |
|
196 | ||
upgraded Mojolicious to v3.7...
|
197 |
Render POD to HTML without preprocessing. |
copy gitweblite soruce code
|
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...
|
204 |
=head2 register |
copy gitweblite soruce code
|
205 | |
upgraded Mojolicious to v3.7...
|
206 |
my $route = $plugin->register(Mojolicious->new); |
207 |
my $route = $plugin->register(Mojolicious->new, {name => 'foo'}); |
|
copy gitweblite soruce code
|
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 |