web commit by http://jeremie.koenig.myopenid.com/: respond with more problems...
[ikiwiki.git] / doc / todo / format_escape.mdwn
1 Since some preprocessor directives insert raw HTML, it would be good to 
2 specify, per-format, how to pass HTML so that it goes through the format 
3 OK. With Markdown we cross our fingers; with reST we use the "raw" 
4 directive.
5
6 I added an extra named parameter to the htmlize hook, which feels sort of
7 wrong, since none of the other hooks take parameters. Let me know what 
8 you think. --Ethan
9
10 Seems fairly reasonable, actually. Shouldn't the `$type` come from `$page`
11 instead of `$destpage` though? Only other obvious change is to make the
12 escape parameter optional, and only call it if set. --[[Joey]]
13
14 > I couldn't figure out what to make it from, but thinking it through, 
15 > yeah, it should be $page. Revised patch follows. --Ethan
16
17 >> I've updated the patch some more, but I think it's incomplete. ikiwiki
18 >> emits raw html when expanding WikiLinks too, and it would need to escape
19 >> those. Assuming that escaping html embedded in the middle of a sentence
20 >> works.. --[[Joey]]
21
22 >>> Revised again. I get around this by making another hook, htmlescapelink,
23 >>> which is called to generate links in whatever language. In addition, it 
24 >>> doesn't (can't?) generate
25 >>> spans, and it doesn't handle inlineable image links. If these were 
26 >>> desired, the approach to take would probably be to use substitution
27 >>> definitions, which would require generating two bits of code for each
28 >>> link/html snippet, and putting one at the end of the paragraph (or maybe
29 >>> the document?).
30 >>> To specify that (for example) Discussion links are meant to be HTML and
31 >>> not rst or whatever, I added a "genhtml" parameter to htmllink. It seems
32 >>> to work -- see <http://ikidev.betacantrips.com/blah.html> for an example.
33 >>> --Ethan
34
35 ## Alternative solution
36
37 [Here](http://www.jk.fr.eu.org/ikiwiki/format-escapes-2.diff) is a patch
38 largely inspired from the one below, which is up to date and written with
39 [[todo/multiple_output_formats]] in mind. "htmlize" hooks are generalized
40 to "convert" ones, which can be registered for any pair of filename
41 extensions.
42
43 Preprocessor directives are allowed to return the content to be inserted
44 as a hash, in any format they want, provided they provide htmlize hooks for it.
45 Pseudo filename extensions (such as `"_link"`) can also be introduced,
46 which aren't used as real extensions but provide useful intermediate types.
47
48 --[[JeremieKoenig]]
49
50 > Wow, this is in many ways a beautiful patch. I did notice one problem,
51 > if a link is converted to rst and then from there to a hyperlink, the
52 > styling info usially added to such a link is lost. I wonder if it would
53 > be better to lose _link stuff and just create link html that is fed into
54 > the rst,html converter. Other advantage to doing that is that link
55 > creation has a rather complex interface, with selflink, attrs, url, and
56 > content parameters.
57
58 > --[[Joey]]
59
60 >> Thanks for the compliment. I must confess that I'm not too familiar with
61 >> rst. I am using this todo item somewhat as a pretext to get the conversion
62 >> stuff in, which I need to implement some other stuff. As a result I was
63 >> less careful with the rst plugin than with the rest of the patch.
64
65 >> This being said, as I understand it rst cannot embed raw html in
66 >> the middle of a paragraph. I just found with more tests that even
67 >> links are a bit tricky, and won't work if they're not surrounded by
68 >> whitespace; the problem is that if we add this space, links
69 >> and preprocessor directives at the beginning of a line will be indented,
70 >> and this means something to rst. Also, rst complains about "?"
71 >> being used multiple times when the page contains more than one broken link,
72 >> apparently it uses it as a name for the reference as well as the link text.
73
74 >> The idea behind _link and other "intermediate
75 >> forms" was also that, when we can use rst's ability to target other output
76 >> formats, raw html won't be included in this process, and that
77 >> complications will happen with all markup languages if html continues
78 >> to be used as the language for preprocessor directive output.
79 >> Of course this could have been postponed until we actually need it,
80 >> but since we do... :-)
81
82 >> I think I will document the limitations, and tune the bugs of the
83 >> rst plugin code to do the most sensible thing after some more reading
84 >> of the rst docs. Expect an updated patch in the next few days, and feel
85 >> free to ask for other adjustments in the meantime.
86
87 >> Beyond being buggy in the least horrible way, I'm afraid I won't have
88 >> much time for ikiwiki in the next two or three weeks (exams),
89 >> but I think that ultimately these limitations could be worked around.
90 >> I'm not sure it is desirable for ikiwiki to know too much about the
91 >> syntax of its markup languages. Maybe the tricky "format" stuff
92 >> the toc plugin does could be used; maybe we need to think about more
93 >> generic ways to put "marks" in the various types of pages, which could
94 >> be expanded afer htmlization, and maybe the convert stuff could be used
95 >> to do this in an elegant way;
96 >> but then this is not very [[multiple_output_formats]] friendly either.
97 >> What do you think?
98
99 >> --[[JeremieKoenig]]
100
101 ## Original patch
102 [[tag patch]]
103
104 <pre>
105 Index: debian/changelog
106 ===================================================================
107 --- debian/changelog    (revision 3197)
108 +++ debian/changelog    (working copy)
109 @@ -24,6 +24,9 @@
110      than just a suggests, since OpenID is enabled by default.
111    * Fix a bug that caused link(foo) to succeed if page foo did not exist.
112    * Fix tags to page names that contain special characters.
113 +  * Based on a patch by Ethan, add a new htmlescape hook, that is called
114 +    when a preprocssor directive emits inline html. The rst plugin uses this
115 +    hook to support inlined raw html.
116  
117    [ Josh Triplett ]
118    * Use pngcrush and optipng on all PNG files.
119 Index: IkiWiki/Render.pm
120 ===================================================================
121 --- IkiWiki/Render.pm   (revision 3197)
122 +++ IkiWiki/Render.pm   (working copy)
123 @@ -96,7 +96,7 @@
124                 if ($page !~ /.*\/\Q$discussionlink\E$/ &&
125                    (length $config{cgiurl} ||
126                     exists $links{$page."/".$discussionlink})) {
127 -                       $template->param(discussionlink => htmllink($page, $page, gettext("Discussion"), noimageinline => 1, forcesubpage => 1));
128 +                       $template->param(discussionlink => htmllink($page, $page, gettext("Discussion"), noimageinline => 1, forcesubpage => 1, genhtml => 1));
129                         $actions++;
130                 }
131         }
132 Index: IkiWiki/Plugin/rst.pm
133 ===================================================================
134 --- IkiWiki/Plugin/rst.pm       (revision 3197)
135 +++ IkiWiki/Plugin/rst.pm       (working copy)
136 @@ -30,15 +30,36 @@
137  html = publish_string(stdin.read(), writer_name='html', 
138         settings_overrides = { 'halt_level': 6, 
139                                'file_insertion_enabled': 0,
140 -                              'raw_enabled': 0 }
141 +                              'raw_enabled': 1 }
142  );
143  print html[html.find('<body>')+6:html.find('</body>')].strip();
144  ";
145  
146  sub import { #{{{
147         hook(type => "htmlize", id => "rst", call => \&htmlize);
148 +       hook(type => "htmlescape", id => "rst", call => \&htmlescape);
149 +       hook(type => "htmlescapelink", id => "rst", call => \&htmlescapelink);
150  } # }}}
151  
152 +sub htmlescapelink ($$;@) { #{{{
153 +       my $url = shift;
154 +       my $text = shift;
155 +       my %params = @_;
156 +
157 +       if ($params{broken}){
158 +               return "`? <$url>`_\ $text";
159 +       }
160 +       else {
161 +               return "`$text <$url>`_";
162 +       }
163 +} # }}}
164 +
165 +sub htmlescape ($) { #{{{
166 +       my $html=shift;
167 +       $html=~s/^/  /mg;
168 +       return ".. raw:: html\n\n".$html;
169 +} # }}}
170 +
171  sub htmlize (@) { #{{{
172         my %params=@_;
173         my $content=$params{content};
174 Index: doc/plugins/write.mdwn
175 ===================================================================
176 --- doc/plugins/write.mdwn      (revision 3197)
177 +++ doc/plugins/write.mdwn      (working copy)
178 @@ -121,6 +121,26 @@
179  The function is passed named parameters: "page" and "content" and should
180  return the htmlized content.
181  
182 +### htmlescape
183 +
184 +       hook(type => "htmlescape", id => "ext", call => \&htmlescape);
185 +
186 +Some markup languages do not allow raw html to be mixed in with the markup
187 +language, and need it to be escaped in some way. This hook is a companion
188 +to the htmlize hook, and is called when ikiwiki detects that a preprocessor
189 +directive is inserting raw html. It is passed the chunk of html in
190 +question, and should return the escaped chunk.
191 +
192 +### htmlescapelink
193 +
194 +       hook(type => "htmlescapelink", id => "ext", call => \&htmlescapelink);
195 +
196 +Some markup languages have special syntax to link to other pages. This hook
197 +is a companion to the htmlize and htmlescape hooks, and it is called when a
198 +link is inserted. It is passed the target of the link and the text of the 
199 +link, and an optional named parameter "broken" if a broken link is being
200 +generated. It should return the correctly-formatted link.
201 +
202  ### pagetemplate
203  
204         hook(type => "pagetemplate", id => "foo", call => \&pagetemplate);
205 @@ -355,6 +375,7 @@
206  * forcesubpage  - set to force a link to a subpage
207  * linktext - set to force the link text to something
208  * anchor - set to make the link include an anchor
209 +* genhtml - set to generate HTML and not escape for correct format
210  
211  #### `readfile($;$)`
212  
213 Index: doc/plugins/rst.mdwn
214 ===================================================================
215 --- doc/plugins/rst.mdwn        (revision 3197)
216 +++ doc/plugins/rst.mdwn        (working copy)
217 @@ -10,10 +10,8 @@
218  Note that this plugin does not interoperate very well with the rest of
219  ikiwiki. Limitations include:
220  
221 -* reStructuredText does not allow raw html to be inserted into
222 -  documents, but ikiwiki does so in many cases, including
223 -  [[WikiLinks|WikiLink]] and many
224 -  [[PreprocessorDirectives|PreprocessorDirective]].
225 +* Some bits of ikiwiki may still assume that markdown is used or embed html
226 +  in ways that break reStructuredText. (Report bugs if you find any.)
227  * It's slow; it forks a copy of python for each page. While there is a
228    perl version of the reStructuredText processor, it is not being kept in
229    sync with the standard version, so is not used.
230 Index: IkiWiki.pm
231 ===================================================================
232 --- IkiWiki.pm  (revision 3197)
233 +++ IkiWiki.pm  (working copy)
234 @@ -469,6 +469,10 @@
235         my $page=shift; # the page that will contain the link (different for inline)
236         my $link=shift;
237         my %opts=@_;
238 +       # we are processing $lpage and so we need to format things in accordance
239 +       # with the formatting language of $lpage. inline generates HTML so links
240 +       # will be escaped seperately.
241 +       my $type=pagetype($pagesources{$lpage});
242  
243         my $bestlink;
244         if (! $opts{forcesubpage}) {
245 @@ -494,12 +498,17 @@
246         }
247         if (! grep { $_ eq $bestlink } map { @{$_} } values %renderedfiles) {
248                 return $linktext unless length $config{cgiurl};
249 -               return "<span><a href=\"".
250 -                       cgiurl(
251 -                               do => "create",
252 -                               page => pagetitle(lc($link), 1),
253 -                               from => $lpage
254 -                       ).
255 +               my $url = cgiurl(
256 +                                do => "create",
257 +                                page => pagetitle(lc($link), 1),
258 +                                from => $lpage
259 +                               );
260 +
261 +               if ($hooks{htmlescapelink}{$type} && ! $opts{genhtml}){
262 +                       return $hooks{htmlescapelink}{$type}{call}->($url, $linktext,
263 +                                                              broken => 1);
264 +               }
265 +               return "<span><a href=\"". $url.
266                         "\">?</a>$linktext</span>"
267         }
268         
269 @@ -514,6 +523,9 @@
270                 $bestlink.="#".$opts{anchor};
271         }
272  
273 +       if ($hooks{htmlescapelink}{$type} && !$opts{genhtml}) {
274 +         return $hooks{htmlescapelink}{$type}{call}->($bestlink, $linktext);
275 +       }
276         return "<a href=\"$bestlink\">$linktext</a>";
277  } #}}}
278  
279 @@ -628,6 +640,14 @@
280                                 preview => $preprocess_preview,
281                         );
282                         $preprocessing{$page}--;
283 +
284 +                       # Handle escaping html if the htmlizer needs it.
285 +                       if ($ret =~ /[<>]/ && $pagesources{$page}) {
286 +                               my $type=pagetype($pagesources{$page});
287 +                               if ($hooks{htmlescape}{$type}) {
288 +                                       return $hooks{htmlescape}{$type}{call}->($ret);
289 +                               }
290 +                       }
291                         return $ret;
292                 }
293                 else {
294 </pre>