]> sipb.mit.edu Git - ikiwiki.git/blob - doc/todo/Resolve_native_reStructuredText_links_to_ikiwiki_pages.mdwn
49be3f30a3a2fda89798d13dc4910522e5e91cd4
[ikiwiki.git] / doc / todo / Resolve_native_reStructuredText_links_to_ikiwiki_pages.mdwn
1 _NB! this page has been refactored, hopefully it is clearer now_  
2 _I propose putting discussion posts somewhere in the vincity of
3 the secttion Individual reStructuredText Issues_
4
5 **Goal**
6
7 To be able to use rst as a first-class markup language in ikiwiki. I think
8 most believe this is almost impossible (ikiwiki is built around markdown).
9
10 **Design**
11
12 **WikiLinks**, first and foremost, are needed for a wiki. rST already allows
13 specifying absolue and relative URL links, and relative links can be used to
14 tie together wiki of rst documents.
15
16 1. Below are links to a small, working implementation for resolving
17    undefined rST references using ikiwiki's mechanism. This is **Proposal 1**
18    for rst WikiLinks.
19
20 2. Looking over at rST-using systems such as trac and MoinMoin; I think it
21    would be wiser to implement wikilinks by the `:role:` mechanism, together
22    with allowing a custom URL scheme to point to wiki links. This is
23    **Proposal 2**.
24
25         This is a simple wiki page, with :wiki:`WikiLinks` and other_ links
26         
27         .. _other: wiki:wikilink
28
29 Benefits of using a `:role:` and a `wiki: page/subpage` URL scheme are
30 following:
31
32 1. rST documents taken out of the context (the wiki) will not fail as bad as
33    if they have lots of Proposal-1 links: They look just the same as valid
34    references, and you have to edit them all.
35    In contrast, should the `:wiki:` role disappear, one line is enough
36    to redefined it and silence all the warnings for the document:
37
38         .. role:: wiki (title)
39
40 *Implementation* there is no implementation of Proposal 2 but it should be
41 doable; adding a local role is trivial. Rewriting `wiki:` links could be
42 done in the format phase(?).
43
44 Now **Directives**: As it is now, ikiwiki goes though (roughly):
45 filter, preprocess, htmlize, format as major stages of content
46 transformation. rST has major problems to work with any HTML that enters the
47 picture before it.
48
49 1. Formatting rST in `htmlize` (as is done now): Raw html can be escaped by
50    raw blocks:
51
52         .. raw:: html
53         
54                 \[[!inline and do stuff]]
55
56    (This can be simplified to alias the above as `.. ikiwiki::`)
57    This escape method works, if ikwiki can be persuaded to maintain the
58    indent when inserting html, so that it stays inside the raw block.
59
60 2. Formatting rST in `filter` (idea)
61    1. rST does not have to see any HTML (raw not needed)
62    2. rST directives can alias ikiwiki syntax:
63      
64         ..ikiwiki:: inline pages= ...
65
66    3. Using rST directives as ikiwiki directives can be complicated;
67       but rST directives allow a direct line (after :: on first line),
68       an option list, and a content block.
69
70
71 **Discussion**
72
73 I guess you (or someone) has been through this before and knows why it
74 simply won't work. But I hoped there was something original in the above;
75 and I know there are wiki installations where rST works. --ulrik
76
77 **Individual reStructuredText Issues**
78
79 * We resolve rST links without definition, we don't help resolving defined
80   relative links, so we don't support specifying link name and target
81   separately.
82
83 > I found out this is possible by using rST subsitutions. So to do [[Version history...|releases]]
84 > you would use:
85
86 > `|releases|_`  
87 > `.. |releases| replace:: Version history...`  
88 > Which does not seem to have an inline equivalent. Using non-resolved links there is the alternative:
89 >
90 > ``Version history <releases/>`_`. --ulrik [kaizer.se]
91
92 **A first implementation: Resolving unmatched links**
93
94 I have a working minimal implementation letting the rst renderer resolve
95 undefined native rST links to ikiwiki pages. I have posted it as one patch at:
96
97 Preview commit: http://github.com/engla/ikiwiki/commit/486fd79e520da1d462f00f40e7a90ab07e9c6fdf  
98 Repository: git://github.com/engla/ikiwiki.git  
99
100 Design issues of the patch:
101
102 The page is rST-parsed once in 'scan' and once in 'htmlize' (the first to generate backlinks). Can the parse output be safely reused?
103
104 > The page content fed to htmlize may be different than that fed to scan,
105 > as directives can change the content. If you cached the input and output
106 > at scan time, you could reuse the cached data at htmlize time for inputs
107 > that are the same -- but that could be a very big cache! --[[Joey]] 
108
109 >> I would propose using a simple heuristic: If you see \[[ anywhere on the
110 >> page, don't cache it. It would be an effective cache for pure-rst wikis
111 >> (without any ikiwiki directives or wikilinks).
112 >> However, I think that if the cache does not work for a big load, it should
113 >> not work at all; small loads are small so they don't matter. --ulrik
114
115 Patch follows:
116
117 ----
118 <pre>
119         From 486fd79e520da1d462f00f40e7a90ab07e9c6fdf Mon Sep 17 00:00:00 2001
120         From: Ulrik Sverdrup <ulrik.sverdrup@gmail.com>
121         Date: Thu, 17 Sep 2009 15:18:50 +0200
122         Subject: [PATCH] rst: Resolve native reStructuredText links to ikiwiki pages
123
124         Links in rST use syntax `Like This`_ or OneWordLink_, and are
125         generally used for relative or absolue links, with an auxiliary
126         definition:
127
128         .. _`Like This`: http://ikiwiki.info
129         .. _OneWordLink: relative
130
131         We can hook into docutils to resolve unresolved links so that rST
132         links without definition can be resolved to wiki pages. This enables
133         WikiLink_ to link to [[WikiLink]] (if no .. _WikiLink is specified).
134
135         Comparing to Ikiwiki's wikilinks
136
137         [[blogging|blog]] specifies a link to the page blog, with the name
138         blogging. In rST we should use blogging_
139
140         .. _blogging: blog
141
142         *However*, note that this patch does not hook into this. What we
143         resolve in this patch is finding the appropriate "_blogging" if it is
144         not found, not resolving the address 'blog'.
145         ---
146          plugins/rst |   46 +++++++++++++++++++++++++++++++++++++++++-----
147          1 files changed, 41 insertions(+), 5 deletions(-)
148
149         diff --git a/plugins/rst b/plugins/rst
150         index a2d07eb..a74baa8 100755
151         --- a/plugins/rst
152         +++ b/plugins/rst
153         @@ -6,22 +6,58 @@
154          # based a little bit on rst.pm by Sergio Talens-Oliag, but only a little bit. :)
155          #
156          # Copyright © martin f. krafft <madduck@madduck.net>
157         +# Copyright © Ulrik Sverdrup <ulrik.sverdrup@gmail.com>, 2009
158         +#
159          # Released under the terms of the GNU GPL version 2
160          #
161         +
162          __name__ = 'rst'
163          __description__ = 'xml-rpc-based ikiwiki plugin to process RST files'
164         -__version__ = '0.3'
165         +__version__ = '0.3+'
166          __author__ = 'martin f. krafft <madduck@madduck.net>'
167          __copyright__ = 'Copyright © ' + __author__
168          __licence__ = 'GPLv2'
169          
170          from docutils.core import publish_parts;
171         +from docutils.writers import html4css1
172          from proxy import IkiWikiProcedureProxy
173          
174         -def rst2html(proxy, *kwargs):
175         -    # FIXME arguments should be treated as a hash, the order could change
176         -    # at any time and break this.
177         -    parts = publish_parts(kwargs[3], writer_name='html',
178         +class IkiwikiWriter(html4css1.Writer):
179         +    def resolve_node(self, node):
180         +        refname = node.get('refname', None)
181         +        if not refname:
182         +            return False
183         +
184         +        bestlink = self.proxy.rpc('bestlink', self.page, refname)
185         +
186         +        node.resolved = 1
187         +        node['class'] = 'wiki'
188         +        del node['refname']
189         +
190         +        if not bestlink:
191         +            rel_url = "#"
192         +        else:
193         +            rel_url = self.proxy.rpc('urlto', bestlink, self.page)
194         +            self.proxy.rpc('add_link', self.page, bestlink)
195         +        node['refuri'] = rel_url
196         +        self.proxy.rpc('debug', "Emitting link %s => %s" % (refname, rel_url))
197         +        return True
198         +
199         +    resolve_node.priority = 1
200         +
201         +    def __init__(self, proxy, page):
202         +        html4css1.Writer.__init__(self)
203         +        self.proxy = proxy
204         +        self.page = page
205         +        self.unknown_reference_resolvers = (self.resolve_node, )
206         +
207         +def rst2html(proxy, *args):
208         +    # args is a list paired by key, value, so we turn it into a dict
209         +    kwargs = dict((k, v) for k, v in zip(*[iter(args)]*2))
210         +    page = kwargs['page']
211         +
212         +    parts = publish_parts(kwargs['content'],
213         +                          writer=IkiwikiWriter(proxy, page),
214                                    settings_overrides = { 'halt_level': 6
215                                                         , 'file_insertion_enabled': 0
216                                                         , 'raw_enabled': 1
217         -- 
218         1.6.4
219
220 </pre>
221 ----