escape markup (oops)
[ikiwiki.git] / doc / todo / Resolve_native_reStructuredText_links_to_ikiwiki_pages.mdwn
1 I have a working minimal implementation letting the rst renderer resolve undefined native rST links to ikiwiki pages. I have posted it as one patch at:
2
3 Preview commit: http://github.com/engla/ikiwiki/commit/486fd79e520da1d462f00f40e7a90ab07e9c6fdf  
4 Repository: git://github.com/engla/ikiwiki.git  
5
6 Design issues of the patch:
7
8 Right now it changes rendering so that undefined pages (previous errors) are resolved to either ikiwiki pages or link to "#". It could be changed (trivially) so that undefined pages give the same error as before. Since it only resolves links that would previously error out, impact on current installations should be minimal.
9
10 The page is rST-parsed once in 'scan' and once in 'htmlize' (the first to generate backlinks). Can the parse output be safely reused?
11
12 > The page content fed to htmlize may be different than that fed to scan,
13 > as directives can change the content. If you cached the input and output
14 > at scan time, you could reuse the cached data at htmlize time for inputs
15 > that are the same -- but that could be a very big cache! --[[Joey]] 
16
17 >> I would propose using a simple heuristic: If you see \[[ anywhere on the
18 >> page, don't cache it. It would be an effective cache for pure-rst wikis
19 >> (without any ikiwiki directives or wikilinks).
20 >> However, I think that if the cache does not work for a big load, it should
21 >> not work at all; small loads are small so they don't matter. --ulrik
22
23 Desing issues in general:
24
25 We resolve rST links without definition, we don't help resolving defined relative links, so we don't support specifying link name and target separately.
26
27 > I found out this is possible by using rST subsitutions. So to do [[Version history...|releases]]
28 > you would use:
29
30 > `|releases|_`  
31 > `.. |releases| replace:: Version history...`  
32 > Which does not seem to have an inline equivalent. Using non-resolved links there is the alternative:
33 >
34 > ``Version history <releases/>`_`. --ulrik [kaizer.se]
35
36
37 Many other issues with rST are of course unresolved, but some might be solved by implementing custom rST directives (which is a supported extension mechanism).
38
39 Patch follows:
40
41 ----
42 <pre>
43         From 486fd79e520da1d462f00f40e7a90ab07e9c6fdf Mon Sep 17 00:00:00 2001
44         From: Ulrik Sverdrup <ulrik.sverdrup@gmail.com>
45         Date: Thu, 17 Sep 2009 15:18:50 +0200
46         Subject: [PATCH] rst: Resolve native reStructuredText links to ikiwiki pages
47
48         Links in rST use syntax `Like This`_ or OneWordLink_, and are
49         generally used for relative or absolue links, with an auxiliary
50         definition:
51
52         .. _`Like This`: http://ikiwiki.info
53         .. _OneWordLink: relative
54
55         We can hook into docutils to resolve unresolved links so that rST
56         links without definition can be resolved to wiki pages. This enables
57         WikiLink_ to link to [[WikiLink]] (if no .. _WikiLink is specified).
58
59         Comparing to Ikiwiki's wikilinks
60
61         [[blogging|blog]] specifies a link to the page blog, with the name
62         blogging. In rST we should use blogging_
63
64         .. _blogging: blog
65
66         *However*, note that this patch does not hook into this. What we
67         resolve in this patch is finding the appropriate "_blogging" if it is
68         not found, not resolving the address 'blog'.
69         ---
70          plugins/rst |   46 +++++++++++++++++++++++++++++++++++++++++-----
71          1 files changed, 41 insertions(+), 5 deletions(-)
72
73         diff --git a/plugins/rst b/plugins/rst
74         index a2d07eb..a74baa8 100755
75         --- a/plugins/rst
76         +++ b/plugins/rst
77         @@ -6,22 +6,58 @@
78          # based a little bit on rst.pm by Sergio Talens-Oliag, but only a little bit. :)
79          #
80          # Copyright © martin f. krafft <madduck@madduck.net>
81         +# Copyright © Ulrik Sverdrup <ulrik.sverdrup@gmail.com>, 2009
82         +#
83          # Released under the terms of the GNU GPL version 2
84          #
85         +
86          __name__ = 'rst'
87          __description__ = 'xml-rpc-based ikiwiki plugin to process RST files'
88         -__version__ = '0.3'
89         +__version__ = '0.3+'
90          __author__ = 'martin f. krafft <madduck@madduck.net>'
91          __copyright__ = 'Copyright © ' + __author__
92          __licence__ = 'GPLv2'
93          
94          from docutils.core import publish_parts;
95         +from docutils.writers import html4css1
96          from proxy import IkiWikiProcedureProxy
97          
98         -def rst2html(proxy, *kwargs):
99         -    # FIXME arguments should be treated as a hash, the order could change
100         -    # at any time and break this.
101         -    parts = publish_parts(kwargs[3], writer_name='html',
102         +class IkiwikiWriter(html4css1.Writer):
103         +    def resolve_node(self, node):
104         +        refname = node.get('refname', None)
105         +        if not refname:
106         +            return False
107         +
108         +        bestlink = self.proxy.rpc('bestlink', self.page, refname)
109         +
110         +        node.resolved = 1
111         +        node['class'] = 'wiki'
112         +        del node['refname']
113         +
114         +        if not bestlink:
115         +            rel_url = "#"
116         +        else:
117         +            rel_url = self.proxy.rpc('urlto', bestlink, self.page)
118         +            self.proxy.rpc('add_link', self.page, bestlink)
119         +        node['refuri'] = rel_url
120         +        self.proxy.rpc('debug', "Emitting link %s => %s" % (refname, rel_url))
121         +        return True
122         +
123         +    resolve_node.priority = 1
124         +
125         +    def __init__(self, proxy, page):
126         +        html4css1.Writer.__init__(self)
127         +        self.proxy = proxy
128         +        self.page = page
129         +        self.unknown_reference_resolvers = (self.resolve_node, )
130         +
131         +def rst2html(proxy, *args):
132         +    # args is a list paired by key, value, so we turn it into a dict
133         +    kwargs = dict((k, v) for k, v in zip(*[iter(args)]*2))
134         +    page = kwargs['page']
135         +
136         +    parts = publish_parts(kwargs['content'],
137         +                          writer=IkiwikiWriter(proxy, page),
138                                    settings_overrides = { 'halt_level': 6
139                                                         , 'file_insertion_enabled': 0
140                                                         , 'raw_enabled': 1
141         -- 
142         1.6.4
143
144 </pre>
145 ----