some answers
[ikiwiki] / 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 ## Design ##
6
7 **Goal**
8
9 To be able to use rst as a first-class markup language in ikiwiki. I think
10 most believe this is almost impossible (ikiwiki is built around markdown).
11
12 ## Wikilinks ##
13
14 **WikiLinks**, first and foremost, are needed for a wiki. rST already allows
15 specifying absolue and relative URL links, and relative links can be used to
16 tie together wiki of rst documents.
17
18 1. Below are links to a small, working implementation for resolving
19    undefined rST references using ikiwiki's mechanism. This is **Proposal 1**
20    for rst WikiLinks.
21
22 2. Looking over at rST-using systems such as trac and MoinMoin; I think it
23    would be wiser to implement wikilinks by the `:role:` mechanism, together
24    with allowing a custom URL scheme to point to wiki links. This is
25    **Proposal 2**.
26
27         This is a simple wiki page, with :wiki:`WikiLinks` and other_ links
28         
29         .. _other: wiki:wikilink
30
31         We can get rid of the role part as well for WikiLinks::
32         
33             .. default-role:: wiki
34         
35         Enables `WikiLinks` but does not impact references such as ``other``
36         This can be made the default for ikiwiki.
37
38 Benefits of using a `:role:` and a `wiki: page/subpage` URL scheme are
39 following:
40
41 1. rST documents taken out of the context (the wiki) will not fail as bad as
42    if they have lots of Proposal-1 links: They look just the same as valid
43    references, and you have to edit them all.
44    In contrast, should the `:wiki:` role disappear, one line is enough
45    to redefined it and silence all the warnings for the document:
46
47         .. role:: wiki (title)
48
49 ### Implementation ###
50
51 Implementation of Proposal-2 wikilinks are in the branch
52 [rst-wikilinks][rst-wl]
53
54
55         This is a simple wiki page, with :wiki:`WikiLinks` and |named| links
56         
57         .. |named| wiki:: Some Page
58
59         We can get rid of the role part as well for WikiLinks::
60         
61             .. default-role:: wiki
62         
63         Enables `WikiLinks` but does not impact references such as ``named``
64         This can be made the default for ikiwiki.
65
66 [rst-wl]: http://github.com/engla/ikiwiki/commits/rst-wikilinks
67
68 **rst-wikilinks** patch series includes changes at the end to use ikiwiki's
69 'htmllink' for the links (which is the only sane thing to do to work in all configurations).
70 This means a :wiki:`Link` should render just exactly like [[Link]] whether
71 the target exists or not.
72
73 On top of **rst-wikilinks** is [rst-customize][rst-custom] which adds two
74 power user features: Global (python) file to read in custom directives
75 (unsafe), and a wikifile as "header" file for all parsed .rst files (safe,
76 but disruptive since all .rst depend on it). Well, the customizations have
77 to be picked and chosen from this, but at least the global python file can
78 be very convenient.
79
80 > Did you consider just including the global rst header text into an item
81 > in the setup file? --[[Joey]] 
82 >
83 >> Then `rst_header` would not be much different from the python script
84 >> `rst_customize`. rst_header is as safe as other files (though disruptive
85 >> as noted), so it should/could be a editable file in the Wiki. A Python
86 >> script of course can not be. There is nothing you can do in the
87 >> rst_header (that you sensibly would do, I think) that couldn't be done in
88 >> the Python script. `rst_header` has very limited use, but it is another
89 >> possibility, mainly for the user-editable aspect. --[[ulrik]]
90 >>
91 >> (I foresaw only two things to be added to the rst_header: the default
92 >> role could be configured there (as with rst_wikirole), and if you have a
93 >> meta-role like :shortcut:, shortcuts could be defined there.)
94 >
95 > I have some discussion on the [docutils mailing list][dml], the developers
96 > of docutils seems to favor "Proposal 1", while I defend my ideas. They
97 > want all users of ReST to use only the basic featureset to remain
98 > compatible, of course. -- [[ulrik]]
99
100 [dml]: http://thread.gmane.org/gmane.text.docutils.user/5376
101
102 Some rst-custom [examples are here](http://kaizer.se/wiki/rst_examples/)
103
104 [rst-custom]: http://github.com/engla/ikiwiki/commits/rst-customize
105
106 ## Directives ##
107
108 Now **Directives**: As it is now, ikiwiki goes though (roughly):
109 filter, preprocess, htmlize, format as major stages of content
110 transformation. rST has major problems to work with any HTML that enters the
111 picture before it.
112
113 1. Formatting rST in `htmlize` (as is done now): Raw html can be escaped by
114    raw blocks:
115
116         .. raw:: html
117         
118                 \[[!inline and do stuff]]
119
120    (This can be simplified to alias the above as `.. ikiwiki::`)
121    This escape method works, if ikwiki can be persuaded to maintain the
122    indent when inserting html, so that it stays inside the raw block.
123
124 2. Formatting rST in `filter` (idea)
125    1. rST does not have to see any HTML (raw not needed)
126    2. rST directives can alias ikiwiki syntax:
127      
128         ..ikiwiki:: inline pages= ...
129
130    3. Using rST directives as ikiwiki directives can be complicated;
131       but rST directives allow a direct line (after :: on first line),
132       an option list, and a content block.
133
134 > You've done a lot of work already, but ...
135
136 > The filter approach seems much simpler than the other approaches
137 > for users to understand, since they can just use identical ikiwiki
138 > markup on rst pages as they would use anywhere else. This is very desirable
139 > if the wiki allows rst in addition to mdwn, since then users don't have
140 > to learn two completly different ways of doing wikilinks and directives.
141 > I also wonder if even those familiar with rst would find entirely natural
142 > the ways you've found to shoehorn in wikilinks, named wikilinks, and ikiwiki
143 > directives?
144
145 > Htmlize in filter avoids these problems. It also leaves open the possibility
146 > that ikiwiki could become smarter about the rendering chain later, and learn
147 > to use a better order for rst (ie, htmlize first). If that later happened,
148 > the htmlize in filter hack could go away. --[[Joey]] 
149
150 > (BTW, the [[plugins/txt]] plugin already does html formatting
151 > in filter, for similar reasons.) --[[Joey]]
152
153 >> Thank you for the comments! Forget the work, it's not so much.
154 >> I'd rank the :wiki: link addition pretty high, and the other changes way
155 >> behind that:
156 >>
157 >> The :wiki:`Wiki Link` syntax is *very* appropriate as rst syntax
158 >> since it fits well with other uses of roles (notice that :RFC:`822`
159 >> inserts a link to RFC822 etc, and that the default role is a *title* role
160 >> (title of some work); thus very appropriate for medium-specific links like
161 >> wiki links. So I'd rank :wiki: links a worthwhile addition regardless of
162 >> outcome here, since it's a very rst-like alternative for those who wish to
163 >> use more rst-like syntax (and documents degrades better outside the wiki as
164 >> noted).
165 >>
166 >>> Unsure about the degredation argument. It will work some of
167 >>> the time, but ikiwiki's [[ikiwiki/subpage/linkingrules]]
168 >>> are sufficiently different from normal html relative link
169 >>> rules that it often won't work. --[[Joey]]
170 >>>
171 >>>> With degradation I mean that if you take a file out of the wiki; the
172 >>>> links degrade to stylized text. If using default role, they degrade to
173 >>>> :title: which renders italicized text (which I find is exactly
174 >>>> appropriate). There is no way for them to degrade into links, except of
175 >>>> course if you reimplement the :wiki: role. You can also respecify
176 >>>> either the default role (the `wikilink` syntax) or the :wiki: role (the
177 >>>> :wiki:`wikilink` syntax) to any other markup, for example None.
178 >>>> --[[ulrik]]
179 >> 
180 >> The named link syntax (just like the :wiki: role) are inspired from
181 >> [trac][tracrst] and a good fit, but only if the wiki is committed to
182 >> using only rst, which I don't think is the case.
183 >>
184 >> The rst-customize changes are very useful for custom directive
185 >> installations (like the sourcecode directive, or shortcut roles I show
186 >> in the examples page), but there might be a way for the user to inject
187 >> docutils addons that I'm missing (one very ugly way would be to stick
188 >> them in sitecustomize.py which affects all Python programs).
189 >>
190 >> With the presented changes, I already have a working RestructuredText
191 >> wiki, but I'm admitting that using .. raw:: html around all directives is
192 >> very ugly (I use few directives: inline, toggle, meta, tag, map)
193 >>
194 >> On filter/htmlize: Well **rst** is clearly antisocial: It can't see HTML,
195 >> and ikiwiki directives are wrappend in paragraph tags. (For wikilinks
196 >> this is probably no problem). So the suggestion about `.. ikiwiki:` is
197 >> partly because it looks good in rst syntax, but also since it would emit
198 >> a div to wrap around the element instead of a paragraph.
199 >>
200 >> I don't know if you mean that rst could be reordered to do htmlize before
201 >> other phases? rst must be before any preprocess hook to avoid seeing any
202 >> HTML.
203 >>
204 >>> One of my long term goals is to refactor all the code in ikiwiki
205 >>> that manually runs the various stages of the render pipeline,
206 >>> into one centralized place. Once that's done, that place can get
207 >>> smart about what order to run the stages, and use a different
208 >>> order for rst. --[[Joey]]
209 >>
210 >> If I'm thinking right, processing to HTML already in filter means any
211 >> processing in scan can be reused directly (or skipped if it's legal to
212 >> emit 'add_link' in filter.)
213 >>
214 >> -- [[ulrik]] 
215
216 >>> Seems it could be, yes. --[[Joey]]
217 >>>
218 >>>> It is not clear how we can work around reST wrapping directives with
219 >>>> paragraph tags. Also, some escaping of xml characters & <> might
220 >>>> happen, but I can't imagine right now what breakage can come from that.
221 >>>> -- [[ulrik]]
222
223 [tracrst]: http://trac.edgewall.org/wiki/WikiRestructuredText
224
225 ### Implementation ###
226
227 Preserving indents in the preprocessor are in branch [pproc-indent][ppi]
228
229 (These simple patches come with a warning: _Those are the first lines of
230 Perl I've ever written!_)
231
232 > This seems like a good idea, since it solves issues for eg, indented
233 > directives in mdwn as well. But, looking at the diff, I see a clear bug:
234 >
235 >       -                               return "[[!$command <span class=\"error\">".
236 >       +                               $result = "[[!$command <span class=\"error\">".
237
238 > That makes it go on and parse an infinitely nested directive chain, instead
239 > of immediatly throwing an error.
240
241 > Also, it seems that the "indent" matching in the regexps may be too broad,
242 > wouldn't it also match whitespace before a directive that was not at the beginning 
243 > of a line, and treat it as an indent? With some bad luck, that could cause mdwn
244 > to put the indented output in a pre block. --[[Joey]] 
245 >
246 >> You are probably right about the bug. I'm not quite sure what the nested
247 >> directives examples looks like, but I must have overlooked how the
248 >> recursion counter works; I thought simply changing if to elif the next
249 >> few lines would solve that. I'm sorry for that!
250 >>
251 >> We don't have to change the `$handle` function at all, if it is possible
252 >> to do the indent substitution all in one line instead of passing it to
253 >> handle, I don't know if it is possible to turn:
254 >>
255 >>              $content =~ s{$regex}{$handle->($1, $2, $3, $4, $5)}eg;
256 >>
257 >> into
258 >>
259 >>              $content =~ s{$regex}{s/^/$1/gm{$handle->($2, $3, $4, $5)}}eg;
260 >>
261 >> Well, no idea how that would be expressed, but I mean, replace the indent
262 >> directly in $handle's return value.
263 >>
264 >>> Yes, in effect just `indent($1, handle->($2,$,4))` --[[Joey]] 
265 >>
266 >> The indent-catching regex is wrong in the way you mention, it has been
267 >> nagigng my mind a bit as well; I think matching start of line + spaces
268 >> and tabs is the only thing we want.
269 >> -- [[ulrik]]
270 >> 
271 >>> Well, seems you want to match the indent at the start of the line containing
272 >>> the directive, even if the directive does not start the line. That would
273 >>> be quite hard to make a regexp do, though. --[[Joey]]
274 >>
275 >> I wasted a long time getting the simpler `indent($1, handle->($2,$,4))` to
276 >> work (remember, I don't know perl at all). Somehow `$1` does not arrive, I
277 >> made a simple testcase that worked, and I conclude something inside $handle
278 >> results in the value of $1 not arriving as it should!
279 >>
280 >> Anyway, instead a very simple incremental patch is in [pproc-indent][ppi]
281 >> where the indentation regex is `(^[ \t]+|)` instead, which seems to work
282 >> very well (and the regex is multiline now as well). I'm happy to rebase the
283 >> changes if you want or you can just squash the four patches 1+3 => 1+1
284 >> -- [[ulrik]]
285
286 [ppi]: http://github.com/engla/ikiwiki/commits/pproc-indent
287
288 ## Discussion ##
289
290 I guess you (or someone) has been through this before and knows why it
291 simply won't work. But I hoped there was something original in the above;
292 and I know there are wiki installations where rST works. --ulrik
293
294 **Individual reStructuredText Issues**
295
296 * We resolve rST links without definition, we don't help resolving defined
297   relative links, so we don't support specifying link name and target
298   separately.
299   
300   * Resolved by |replacement| links with the wiki:: directive.
301
302 **A first implementation: Resolving unmatched links**
303
304 I have a working minimal implementation letting the rst renderer resolve
305 undefined native rST links to ikiwiki pages. I have posted it as one patch at:
306
307 Preview commit: http://github.com/engla/ikiwiki/commit/486fd79e520da1d462f00f40e7a90ab07e9c6fdf  
308 Repository: git://github.com/engla/ikiwiki.git  
309
310 Design issues of the patch:
311
312 The page is rST-parsed once in 'scan' and once in 'htmlize' (the first to generate backlinks). Can the parse output be safely reused?
313
314 > The page content fed to htmlize may be different than that fed to scan,
315 > as directives can change the content. If you cached the input and output
316 > at scan time, you could reuse the cached data at htmlize time for inputs
317 > that are the same -- but that could be a very big cache! --[[Joey]] 
318
319 >> I would propose using a simple heuristic: If you see \[[ anywhere on the
320 >> page, don't cache it. It would be an effective cache for pure-rst wikis
321 >> (without any ikiwiki directives or wikilinks).
322 >> However, I think that if the cache does not work for a big load, it should
323 >> not work at all; small loads are small so they don't matter. --ulrik
324
325 -----
326
327 Another possiblity is using empty url for wikilinks (gitit uses this approach), for example:
328
329     `SomePage <>`_
330
331 Since it uses *empty* url, I would like to call it *proposal 0* :-)  --[weakish]
332
333 [weakish]: http://weakish.pigro.net