File Coverage

blib/lib/Ado/Plugin/MarkdownRenderer.pm
Criterion Covered Total %
statement 46 47 97.8
branch 7 12 58.3
condition 20 27 74.0
subroutine 6 6 100.0
pod 2 2 100.0
total 81 94 86.1


line stmt bran cond sub pod time code
1             package Ado::Plugin::MarkdownRenderer;
2 23     23   15069 use Mojo::Base 'Ado::Plugin';
  23         78  
  23         120  
3 23     23   3153 use Mojo::File qw(path);
  23         42  
  23         14332  
4             File::Basename->import('fileparse');
5             File::Spec::Functions->import(qw(catfile catdir));
6             Mojo::ByteStream->import('b');
7              
8             sub register {
9 24     24 1 5192 my ($self, $app, $config) = shift->initialise(@_);
10              
11             #Make sure we have all we need from config files.
12 24   100     92 $config->{md_renderer} ||= 'Text::MultiMarkdown';
13 24   100     74 $config->{md_method} ||= 'markdown';
14 24   100     69 $config->{md_options} ||= {use_wikilinks => 1,};
15 24   100     65 $config->{md_helper} ||= 'md_to_html';
16 24   66     96 $config->{md_root} ||= $app->home->rel_file('public/doc');
17 24   33     277 $config->{md_articles_root} ||= $app->home->rel_file('public/articles');
18 24   100     615 $config->{md_file_sufixes} ||= ['.md'];
19              
20 24 50       114 if ($config->{md_renderer} eq 'Text::MultiMarkdown') {
21 24         7105 require Text::MultiMarkdown;
22 24     50   381049 $app->helper($config->{md_helper} => sub { md_to_html(shift, $config, @_) });
  50         2239  
23             $app->helper(
24             markdown => sub {
25 29     29   3414 my $c = shift;
26 29         148 return Text::MultiMarkdown::markdown(@_);
27             }
28 24         745 );
29              
30             }
31              
32             #make plugin configuration available for later in the app
33 24         417 $app->config(__PACKAGE__, $config);
34 24         1045 return $self;
35             }
36              
37             sub md_to_html {
38 50     50 1 156 my ($c, $config, $file_path) = @_;
39 50   50     200 $file_path ||= ($c->stash('md_file') || return '');
      66        
40              
41             #remove anchors
42 50         402 $file_path =~ s{[^#]#.+}{};
43 50 0       103 unless ($file_path) { $c->reply->not_found() && return '' }
  0 50       0  
44 50         331 my $fullname = catfile($config->{md_root}, $file_path);
45 50         573 $c->debug("md_file: $file_path; \$fullname: $fullname");
46              
47 50         1030 my ($name, $path, $suffix) = fileparse($fullname, @{$config->{md_file_sufixes}});
  50         1603  
48 50         315 my $html_filepath = catfile($path, "$name.html");
49              
50             #Reuse previously produced html file if md_file is older than the html file.
51 50 100 66     1739 if ( $config->{md_reuse_produced_html}
      66        
52             && -s $html_filepath
53             && (stat($fullname))[9] < (stat($html_filepath))[9])
54             {
55 24         117 $c->debug('Found ' . $html_filepath);
56 24         503 return b(path($html_filepath)->slurp)->decode;
57             }
58              
59             #404 Not Found
60 26         130 my $md_filepath = catfile($path, "$name$suffix");
61 26 50       464 unless (-s $md_filepath) { $c->reply->not_found() && return '' }
  1 100       11  
62              
63 25         96 my $markdown = path($md_filepath)->slurp;
64 25         2454 my $self_url = $c->url_for()->to_string;
65 25         14091 my %options = (%{$config->{md_options}}, self_url => $self_url);
  25         162  
66 25         261 my $html = $c->markdown($markdown, \%options);
67 25         361460 $c->debug($c->dumper({'%options' => \%options, '$html_filepath' => $html_filepath}));
68 25         722 path($html_filepath)->spurt($html);
69 25         4412 return b($html)->decode;
70             }
71              
72             1;
73              
74              
75             =pod
76              
77             =encoding utf8
78              
79             =head1 NAME
80              
81             Ado::Plugin::MarkDownRenderer - Render markdown to HTML
82              
83              
84             =head1 SYNOPSIS
85              
86             #1. Use one or more markup parsers
87             plugins => [
88             #...
89             #use default configuration
90             'markdown_renderer',
91              
92             #Create your own Text::Trac based wiki
93             {name => 'markdown_renderer', config => {
94             md_renderer =>'Text::Trac',
95             md_options => {
96             trac_url => '/wiki',
97             disable_links => [ qw( changeset ticket ) ],
98             },
99             md_method => 'parse',
100             md_helper =>'trac_to_html'
101             }},
102             #...
103             ],
104              
105             #2. Describe your routes
106             routes => [
107             #markdown_renderer route is already configured
108             #in etc/plugins/markdown_renderer.conf.
109              
110             #Your own great enterprise wiki
111             {route => '/wiki/*md_file', via => ['GET'],
112             to => 'wiki#show',},
113             #...
114             ],
115              
116             #3. Write your controller
117             package Ado::Control::Wiki;
118             use Mojo::Base 'Ado::Control';
119             #...
120              
121             =head1 DESCRIPTION
122              
123             L is a markdown renderer (маани, маани!)
124              
125             You only need to create a controller for your enterprise wiki and use
126             the L helper provided by this plugin.
127             See L for an example.
128              
129             You may use this plugin to load and use other markup languages parsers
130             and converters to HTML.
131              
132             The code of this plugin is a good example for learning to build new plugins,
133             you're welcome to fork it.
134              
135             =head1 OPTIONS
136              
137             The following options can be set in C
138             or C. You can find default options in
139             C. C prefix is short for "markup
140             document" or "markdown".
141              
142             =head2 md_renderer
143              
144             md_renderer => 'Text::MultiMarkdown',
145              
146             The class to load. This option exists because the user may want to use
147             L or L instead.
148              
149             =head2 md_method
150              
151             md_method => 'markdown',
152              
153             Method that will be used internally to produce the C<$HTML>.
154             Can also be a code reference.
155             First parameter is the md_renderer instance and the
156             second is the markdown text.
157              
158             =head2 md_options
159              
160             md_options => {
161             use_wikilinks => 1,
162             base_url => '/docs',
163             },
164              
165             These options will be passed to the md_renderer constructor.
166             They are specific for each markup parser so look at it's documentation.
167              
168             =head2 md_helper
169              
170             md_helper => 'md_to_html',
171              
172             Helper name. You may want to change this if you want to have
173             different helpers for different markup converters,
174             configurations, applications etc. in the same ado instance.
175             Default helper name is L.
176              
177             =head2 md_root
178              
179             md_root => app->home->rel_dir('public/doc'),
180              
181             Directory where the raw files reside.
182              
183             =head2 md_articles_root
184              
185             md_articles_root => app->home->rel_dir('public/articles'),
186              
187             Directory used by L where the raw markdown files reside
188             and where the static HTML files are generated.
189              
190              
191             =head2 md_file_sufixes
192              
193             md_file_sufixes => ['.md'],
194              
195             File-suffixes supported by your renderer.
196              
197             =head2 md_reuse_produced_html
198              
199             md_reuse_produced_html => 1,
200              
201             Do not convert files on every request but reuse already produced html files.
202              
203              
204             =head1 HELPERS
205              
206             L exports the following helpers for use in
207             L methods and templates.
208              
209             =head2 markdown
210              
211             Accepts markdown text and options. Returns HTML.
212             Accepts the same parameters as L
213              
214             #in a controller
215             $c->render(text=>$c->markdown($text));
216              
217             #in a template
218             %==markdown($text)
219              
220             =head2 md_to_html
221              
222             Given a Markdown string returns CarticleE$htmlE/articleE>
223             produced by the converter - L by default.
224             You may want to use your own helper name. See L.
225              
226             #Markdown from $MOJO_HOME/public/doc/bg/intro.md
227             #http://example.com/doc/bg/intro.md
228             my $html = $c->md_to_html();
229              
230             #Markdown from arbitrary file
231             my $html_string = $c->md_to_html($some_filepath);
232              
233             % #in a template
234             <%= md_to_html();%>
235             % #
$html
236              
237             =head1 METHODS
238              
239             L inherits all methods from
240             L and implements the following new ones.
241              
242             =head2 register
243              
244             my $plugin = $app->plugin('markdown_renderer' => $OPTIONS);
245              
246             Register renderer and helper in L. Return $self.
247              
248             =head1 SPONSORS
249              
250             The original author
251              
252             Become a sponsor and help make L the ERP for the enterprise!
253              
254             =head1 SEE ALSO
255              
256             L, L,
257             L, L,
258             L
259             L, L.
260              
261             =head1 AUTHOR
262              
263             Красимир Беров (Krasimir Berov)
264              
265             =head1 COPYRIGHT AND LICENSE
266              
267             Copyright 2013-2014 Красимир Беров (Krasimir Berov).
268              
269             This program is free software, you can redistribute it and/or
270             modify it under the terms of the
271             GNU Lesser General Public License v3 (LGPL-3.0).
272             You may copy, distribute and modify the software provided that
273             modifications are open source. However, software that includes
274             the license may release under a different license.
275              
276             See http://opensource.org/licenses/lgpl-3.0.html for more information.
277              
278             =cut