clarifications. and indent one of joey's oneliner responses.
[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 ## 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 Some rst-custom [examples are here](http://kaizer.se/wiki/rst_examples/)
92
93 [rst-custom]: http://github.com/engla/ikiwiki/commits/rst-customize
94
95 ## Directives ##
96
97 Now **Directives**: As it is now, ikiwiki goes though (roughly):
98 filter, preprocess, htmlize, format as major stages of content
99 transformation. rST has major problems to work with any HTML that enters the
100 picture before it.
101
102 1. Formatting rST in `htmlize` (as is done now): Raw html can be escaped by
103    raw blocks:
104
105         .. raw:: html
106         
107                 \[[!inline and do stuff]]
108
109    (This can be simplified to alias the above as `.. ikiwiki::`)
110    This escape method works, if ikwiki can be persuaded to maintain the
111    indent when inserting html, so that it stays inside the raw block.
112
113 2. Formatting rST in `filter` (idea)
114    1. rST does not have to see any HTML (raw not needed)
115    2. rST directives can alias ikiwiki syntax:
116      
117         ..ikiwiki:: inline pages= ...
118
119    3. Using rST directives as ikiwiki directives can be complicated;
120       but rST directives allow a direct line (after :: on first line),
121       an option list, and a content block.
122
123 > You've done a lot of work already, but ...
124
125 > The filter approach seems much simpler than the other approaches
126 > for users to understand, since they can just use identical ikiwiki
127 > markup on rst pages as they would use anywhere else. This is very desirable
128 > if the wiki allows rst in addition to mdwn, since then users don't have
129 > to learn two completly different ways of doing wikilinks and directives.
130 > I also wonder if even those familiar with rst would find entirely natural
131 > the ways you've found to shoehorn in wikilinks, named wikilinks, and ikiwiki
132 > directives?
133
134 > Htmlize in filter avoids these problems. It also leaves open the possibility
135 > that ikiwiki could become smarter about the rendering chain later, and learn
136 > to use a better order for rst (ie, htmlize first). If that later happened,
137 > the htmlize in filter hack could go away. --[[Joey]] 
138
139 > (BTW, the [[plugins/txt]] plugin already does html formatting
140 > in filter, for similar reasons.) --[[Joey]]
141
142 >> Thank you for the comments! Forget the work, it's not so much.
143 >> I'd rank the :wiki: link addition pretty high, and the other changes way
144 >> behind that:
145 >>
146 >> The :wiki:`Wiki Link` syntax is *very* appropriate as rst syntax
147 >> since it fits well with other uses of roles (notice that :RFC:`822`
148 >> inserts a link to RFC822 etc, and that the default role is a *title* role
149 >> (title of some work); thus very appropriate for medium-specific links like
150 >> wiki links. So I'd rank :wiki: links a worthwhile addition regardless of
151 >> outcome here, since it's a very rst-like alternative for those who wish to
152 >> use more rst-like syntax (and documents degrades better outside the wiki as
153 >> noted).
154 >>
155 >>> Unsure about the degredation argument. It will work some of
156 >>> the time, but ikiwiki's [[ikiwiki/subpage/linkingrules]]
157 >>> are sufficiently different from normal html relative link
158 >>> rules that it often won't work. --[[Joey]]
159 >>>
160 >>>> With degradation I mean that if you take a file out of the wiki; the
161 >>>> links degrade to stylized text. If using default role, they degrade to
162 >>>> :title: which renders italicized text (which I find is exactly
163 >>>> appropriate). There is no way for them to degrade into links, except of
164 >>>> course if you reimplement the :wiki: role. You can also respecify
165 >>>> either the default role (the `wikilink` syntax) or the :wiki: role (the
166 >>>> :wiki:`wikilink` syntax) to any other markup, for example None.
167 >>>> --[[ulrik]]
168 >> 
169 >> The named link syntax (just like the :wiki: role) are inspired from trac
170 >> and a good fit, but only if the wiki is committed to using only rst,
171 >> which I don't think is the case.
172 >>
173 >> The rst-customize changes are very useful for custom directive
174 >> installations (like the sourcecode directive, or shortcut roles I show
175 >> in the examples page), but there might be a way for the user to inject
176 >> docutils addons that I'm missing (one very ugly way would be to stick
177 >> them in sitecustomize.py which affects all Python programs).
178 >>
179 >> With the presented changes, I already have a working RestructuredText
180 >> wiki, but I'm admitting that using .. raw:: html around all directives is
181 >> very ugly (I use few directives: inline, toggle, meta, tag, map)
182 >>
183 >> On filter/htmlize: Well **rst** is clearly antisocial: It can't see HTML,
184 >> and ikiwiki directives are wrappend in paragraph tags. (For wikilinks
185 >> this is probably no problem). So the suggestion about `.. ikiwiki:` is
186 >> partly because it looks good in rst syntax, but also since it would emit
187 >> a div to wrap around the element instead of a paragraph.
188 >>
189 >> I don't know if you mean that rst could be reordered to do htmlize before
190 >> other phases? rst must be before any preprocess hook to avoid seeing any
191 >> HTML.
192 >>
193 >>> One of my long term goals is to refactor all the code in ikiwiki
194 >>> that manually runs the various stages of the render pipeline,
195 >>> into one centralized place. Once that's done, that place can get
196 >>> smart about what order to run the stages, and use a different
197 >>> order for rst. --[[Joey]]
198 >>
199 >> If I'm thinking right, processing to HTML already in filter means any
200 >> processing in scan can be reused directly (or skipped if it's legal to
201 >> emit 'add_link' in filter.)
202 >>
203 >> -- [[ulrik]] 
204
205 >>> Seems it could be, yes. --[[Joey]]
206
207 ### Implementation ###
208
209 Preserving indents in the preprocessor are in branch [pproc-indent][ppi]
210
211 (These simple patches come with a warning: _Those are the first lines of
212 Perl I've ever written!_)
213
214 > This seems like a good idea, since it solves issues for eg, indented
215 > directives in mdwn as well. But, looking at the diff, I see a clear bug:
216 >
217 >       -                               return "[[!$command <span class=\"error\">".
218 >       +                               $result = "[[!$command <span class=\"error\">".
219
220 > That makes it go on and parse an infinitely nested directive chain, instead
221 > of immediatly throwing an error.
222
223 > Also, it seems that the "indent" matching in the regexps may be too broad,
224 > wouldn't it also match whitespace before a directive that was not at the beginning 
225 > of a line, and treat it as an indent? With some bad luck, that could cause mdwn
226 > to put the indented output in a pre block. --[[Joey]] 
227 >
228 >> You are probably right about the bug. I'm not quite sure what the nested
229 >> directives examples looks like, but I must have overlooked how the
230 >> recursion counter works; I thought simply changing if to elif the next
231 >> few lines would solve that. I'm sorry for that!
232 >>
233 >> We don't have to change the `$handle` function at all, if it is possible
234 >> to do the indent substitution all in one line instead of passing it to
235 >> handle, I don't know if it is possible to turn:
236 >>
237 >>              $content =~ s{$regex}{$handle->($1, $2, $3, $4, $5)}eg;
238 >>
239 >> into
240 >>
241 >>              $content =~ s{$regex}{s/^/$1/gm{$handle->($2, $3, $4, $5)}}eg;
242 >>
243 >> Well, no idea how that would be expressed, but I mean, replace the indent
244 >> directly in $handle's return value.
245 >>
246 >>> Yes, in effect just `indent($1, handle->($2,$,4))` --[[Joey]] 
247 >>
248 >> The indent-catching regex is wrong in the way you mention, it has been
249 >> nagigng my mind a bit as well; I think matching start of line + spaces
250 >> and tabs is the only thing we want.
251 >> -- [[ulrik]]
252 >> 
253 >>> Well, seems you want to match the indent at the start of the line containing
254 >>> the directive, even if the directive does not start the line. That would
255 >>> be quite hard to make a regexp do, though. --[[Joey]]
256
257 [ppi]: http://github.com/engla/ikiwiki/commits/pproc-indent
258
259 ## Discussion ##
260
261 I guess you (or someone) has been through this before and knows why it
262 simply won't work. But I hoped there was something original in the above;
263 and I know there are wiki installations where rST works. --ulrik
264
265 **Individual reStructuredText Issues**
266
267 * We resolve rST links without definition, we don't help resolving defined
268   relative links, so we don't support specifying link name and target
269   separately.
270   
271   * Resolved by |replacement| links with the wiki:: directive.
272
273 **A first implementation: Resolving unmatched links**
274
275 I have a working minimal implementation letting the rst renderer resolve
276 undefined native rST links to ikiwiki pages. I have posted it as one patch at:
277
278 Preview commit: http://github.com/engla/ikiwiki/commit/486fd79e520da1d462f00f40e7a90ab07e9c6fdf  
279 Repository: git://github.com/engla/ikiwiki.git  
280
281 Design issues of the patch:
282
283 The page is rST-parsed once in 'scan' and once in 'htmlize' (the first to generate backlinks). Can the parse output be safely reused?
284
285 > The page content fed to htmlize may be different than that fed to scan,
286 > as directives can change the content. If you cached the input and output
287 > at scan time, you could reuse the cached data at htmlize time for inputs
288 > that are the same -- but that could be a very big cache! --[[Joey]] 
289
290 >> I would propose using a simple heuristic: If you see \[[ anywhere on the
291 >> page, don't cache it. It would be an effective cache for pure-rst wikis
292 >> (without any ikiwiki directives or wikilinks).
293 >> However, I think that if the cache does not work for a big load, it should
294 >> not work at all; small loads are small so they don't matter. --ulrik
295