789a70ac752b25c2c7aec04d0c79dd61a66f1775
[ikiwiki.git] / IkiWiki / Plugin / rst.pm
1 #!/usr/bin/perl
2 # Very simple reStructuredText processor.
3 #
4 # This plugin calls python and requires python-docutils to transform the text
5 # into html.
6 #
7 # Its main problem is that it does not support ikiwiki's WikiLinks nor
8 # Preprocessor Directives.
9 #
10 # Probably Wikilinks and Preprocessor Directives should support a list of
11 # extensions to process (i.e. the linkify function could be transformed into
12 # reStructuredText instead of HTML using a hook on rst.py instead of the
13 # current linkify function)
14 #
15 # by Sergio Talens-Oliag <sto@debian.org>
16
17 package IkiWiki::Plugin::rst;
18
19 use warnings;
20 use strict;
21 use IkiWiki;
22 use IPC::Open2;
23
24 # Simple python script, maybe it should be implemented using an external script.
25 # The settings_overrides are given to avoid potential security risks when
26 # reading external files or if raw html is included on rst pages.
27 my $pyCmnd = "
28 from docutils.core import publish_string;
29 from sys import stdin;
30 html = publish_string(stdin.read(), writer_name='html', 
31        settings_overrides = { 'halt_level': 6, 
32                               'file_insertion_enabled': 0,
33                               'raw_enabled': 0 }
34 );
35 print html[html.find('<body>')+6:html.find('</body>')].strip();
36 ";
37
38 sub import { #{{{
39         IkiWiki::hook(type => "htmlize", id => "rst", call => \&htmlize);
40 } # }}}
41
42 sub htmlize (@) { #{{{
43         my %params=@_;
44         my $content=$params{content};
45
46         my $tries=10;
47         my $pid;
48         while (1) {
49                 eval {
50                         # Try to call python and run our command
51                         $pid=open2(*IN, *OUT, "python", "-c",  $pyCmnd)
52                                 or return $content;
53                 };
54                 last unless $@;
55                 $tries--;
56                 if ($tries < 1) {
57                         IkiWiki::debug("failed to run python to convert rst: $@");
58                         return $content;
59                 }
60         }
61         # open2 doesn't respect "use open ':utf8'"
62         binmode (IN, ':utf8');
63         binmode (OUT, ':utf8');
64         
65         print OUT $content;
66         close OUT;
67
68         local $/ = undef;
69         my $ret=<IN>;
70         close IN;
71         waitpid $pid, 0;
72
73         return $ret;
74 } # }}}
75
76 1