From 65dca9f89d82cc512f1c10ac8cf70696243e650a Mon Sep 17 00:00:00 2001 From: joey Date: Mon, 15 Oct 2007 16:33:02 +0000 Subject: [PATCH 1/1] * Rewritten rst plugin by madduck is a python program that communicates with ikiwiki via XML RPC. This should be much faster than the old plugin that had to fork python for every rst page render. Note that if you use the rst plugin, you now need to have the RPC::XML perl module installed. --- IkiWiki/Plugin/rst.pm | 69 ------------------ debian/changelog | 6 +- debian/copyright | 8 +- doc/plugins/rst.mdwn | 10 +-- doc/plugins/write/external.mdwn | 6 +- doc/todo/rst_plugin_python_rewrite.mdwn | 2 + plugins/rst | 97 +++++++++++++++++++++++++ 7 files changed, 116 insertions(+), 82 deletions(-) delete mode 100644 IkiWiki/Plugin/rst.pm create mode 100755 plugins/rst diff --git a/IkiWiki/Plugin/rst.pm b/IkiWiki/Plugin/rst.pm deleted file mode 100644 index 30f5d16d8..000000000 --- a/IkiWiki/Plugin/rst.pm +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/perl -# Very simple reStructuredText processor. -# -# This plugin calls python and requires python-docutils to transform the text -# into html. -# -# Its main problem is that it does not support ikiwiki's WikiLinks nor -# Preprocessor Directives. -# -# Probably Wikilinks and Preprocessor Directives should support a list of -# extensions to process (i.e. the linkify function could be transformed into -# reStructuredText instead of HTML using a hook on rst.py instead of the -# current linkify function) -# -# by Sergio Talens-Oliag - -package IkiWiki::Plugin::rst; - -use warnings; -use strict; -use IkiWiki 2.00; -use IPC::Open2; - -# Simple python script, maybe it should be implemented using an external script. -# The settings_overrides are given to avoid potential security risks when -# reading external files or if raw html is included on rst pages. -my $pyCmnd = " -from docutils.core import publish_string; -from sys import stdin; -html = publish_string(stdin.read(), writer_name='html', - settings_overrides = { 'halt_level': 6, - 'file_insertion_enabled': 0, - 'raw_enabled': 1 } -); -print html[html.find('')+6:html.find('')].strip(); -"; - -sub import { #{{{ - hook(type => "htmlize", id => "rst", call => \&htmlize); -} # }}} - -sub htmlize (@) { #{{{ - my %params=@_; - my $content=$params{content}; - - my $pid; - my $sigpipe=0; - $SIG{PIPE}=sub { $sigpipe=1 }; - $pid=open2(*IN, *OUT, "python", "-c", $pyCmnd); - - # open2 doesn't respect "use open ':utf8'" - binmode (IN, ':utf8'); - binmode (OUT, ':utf8'); - - print OUT $content; - close OUT; - - local $/ = undef; - my $ret=; - close IN; - waitpid $pid, 0; - - return $content if $sigpipe; - $SIG{PIPE}="DEFAULT"; - - return $ret; -} # }}} - -1 diff --git a/debian/changelog b/debian/changelog index 760fc46f2..5250783ca 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,8 +17,12 @@ ikiwiki (2.10) UNRELEASED; urgency=low * Add a "createlink" class attribute to the span for wikilinks pointing to not-yet-existing pages. I don't have a useful style defined for that though. + * Rewritten rst plugin by madduck is a python program that communicates with + ikiwiki via XML RPC. This should be much faster than the old plugin that + had to fork python for every rst page render. Note that if you use + the rst plugin, you now need to have the RPC::XML perl module installed. - -- Joey Hess Sat, 13 Oct 2007 19:05:42 -0400 + -- Joey Hess Mon, 15 Oct 2007 12:20:15 -0400 ikiwiki (2.9) unstable; urgency=low diff --git a/debian/copyright b/debian/copyright index ab85fe424..2681da807 100644 --- a/debian/copyright +++ b/debian/copyright @@ -58,10 +58,6 @@ Files: topography.pm Copyright: © 2006 Recai Oktaş License: GPL-2+ -Files: rst.pm -Copyright: © 2006 Sergio Talens-Oliag -License: GPL-2+ - Files: map.pm Copyright: © 2006 Alessandro Dotti Contra License: GPL-2+ @@ -78,6 +74,10 @@ Files: polygen.pm, pagestats.pm Copyright: © 2006 Enrico Zini License: GPL-2+ +Files: plugins/rst +Copyright: © martin f. krafft +License: GPL-2 + Files: doc/logo/* Copyright: © 2006 Recai Oktaş License: GPL-2+ diff --git a/doc/plugins/rst.mdwn b/doc/plugins/rst.mdwn index 7250e46a1..1f8073517 100644 --- a/doc/plugins/rst.mdwn +++ b/doc/plugins/rst.mdwn @@ -1,11 +1,10 @@ -[[template id=plugin name=rst author="Sergio Talens-Oliag"]] +[[template id=plugin name=rst author="martin f. krafft"]] [[tag type/format]] -[[tag type/slow]] This plugin lets ikwiki convert files with names ending in ".rst" to html. It uses the [reStructuredText](http://docutils.sourceforge.net/rst.html) -markup syntax. You need to have the python-docutils module installed to use -it. +markup syntax. You need to have [[cpan RPC::XML]], python and the +python-docutils module installed to use it. Note that this plugin does not interoperate very well with the rest of ikiwiki. Limitations include: @@ -13,9 +12,6 @@ ikiwiki. Limitations include: * There are issues with inserting raw html into documents, as ikiwiki does with [[WikiLinks|WikiLink]] and many [[PreprocessorDirectives|PreprocessorDirective]]. -* It's slow; it forks a copy of python for each page. While there is a - perl version of the reStructuredText processor, it is not being kept in - sync with the standard version, so is not used. So while you may find this useful for importing old files into your wiki, using this as your main markup language in ikiwiki isn't recommended at diff --git a/doc/plugins/write/external.mdwn b/doc/plugins/write/external.mdwn index e699e43e1..0abc9b0a0 100644 --- a/doc/plugins/write/external.mdwn +++ b/doc/plugins/write/external.mdwn @@ -8,6 +8,10 @@ written in perl, but is intended to be an example of how to write an external plugin in your favorite programming language. Wow us at how much easier you can do the same thing in your favorite language. ;-) +There's now a second external plugin, the [[rst]] plugin, written in +python. (Could someone convert it into a python library that can be used by +other plugins?) + [[toc ]] ## How external plugins use XML RPC @@ -87,7 +91,7 @@ to 1. Since XML RPC can't pass around references to objects, it can't be used with functions that take or return such references. That means you can't -use XML RPC for `cgi` or `formbuilder` hooks (which are passed CGI and +100% use XML RPC for `cgi` or `formbuilder` hooks (which are passed CGI and FormBuilder perl objects), or use it to call `template()` (which returns a perl HTML::Template object). diff --git a/doc/todo/rst_plugin_python_rewrite.mdwn b/doc/todo/rst_plugin_python_rewrite.mdwn index 7626f03a3..222fdb177 100644 --- a/doc/todo/rst_plugin_python_rewrite.mdwn +++ b/doc/todo/rst_plugin_python_rewrite.mdwn @@ -3,3 +3,5 @@ rendered. Now that ikiwiki supports plugins written in [[other_languages|plugins/write/external]], it would be excellent if someone could rewrite the rst plugin as a pure python external plugin. It would then run nice and quick. + +[[done]], thanks to madduck! diff --git a/plugins/rst b/plugins/rst new file mode 100755 index 000000000..abf835e2e --- /dev/null +++ b/plugins/rst @@ -0,0 +1,97 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# rstproc — xml-rpc-based ikiwiki plugin to process RST files +# +# TODO: the top of this file should be converted to a python library for +# ikiwiki plugins +# +# based a little bit on rst.pm by Sergio Talens-Oliag, but only a little bit. :) +# +# Copyright © martin f. krafft +# Released under the terms of the GNU GPL version 2 + +__name__ = 'rstproc' +__description__ = 'xml-rpc-based ikiwiki plugin to process RST files' +__version__ = '0.2' +__author__ = 'martin f. krafft ' +__copyright__ = 'Copyright © ' + __author__ +__licence__ = 'GPLv2' + +from docutils.core import publish_string; +import posix +import select +import sys +import xmlrpclib +import xml.parsers.expat +from SimpleXMLRPCServer import SimpleXMLRPCDispatcher + +def write(s): + # no comment + sys.stdout.write(s) + sys.stdout.flush() + +def debug(s): + print >>sys.stderr, __name__ + ':DEBUG:' + s + sys.stderr.flush() + +def rpc_read(processor): + acc = '' + ret = None + while True: + line = sys.stdin.readline() + if line is None: continue + if len(line) == 0: sys.exit(posix.EX_OK) +# debug('read line: ' + line) + acc += line + try: + ret = processor(acc) +# debug('processed: ' + acc) +# debug('got back: ' + ret.__class__.__name__) + return ret + except xml.parsers.expat.ExpatError: +# debug('request invalid or incomplete: ' + acc) + pass + return None + +def rpc_call(cmd, **kwargs): + call = xmlrpclib.dumps(sum(kwargs.items(), ()), cmd) + write(call + '\n') + resp = rpc_read(lambda resp: resp) + +class SimpleStdinOutXMLRPCHandler(SimpleXMLRPCDispatcher): + + def __init__(self): + SimpleXMLRPCDispatcher.__init__(self) + + def process_request(self, req): + write(self._marshaled_dispatch(req)) + + def handle_request(self): + def processor(req): + self.process_request(req) + while True: + ret = rpc_read(processor) + if ret is not None: return ret + +def rst2html(*kwargs): + # FIXME arguments should be treated as a hash, the order could change + # at any time and break this. + html = publish_string(kwargs[3], writer_name='html', + settings_overrides = { 'halt_level': 6 + , 'file_insertion_enabled': 0 + , 'raw_enabled': 1 + }) + content = html.split('
', 1)[1] + content = content.split('
\n')[:-1][0].strip() +# debug('content = ' + content) + return content + +def importme(): + rpc_call('hook', type='htmlize', id='rst', call='rst2html') + +handler = SimpleStdinOutXMLRPCHandler() +handler.register_function(importme, name='import') +handler.register_function(rst2html) +while True: + handler.handle_request() -- 2.44.0