ikiwiki (3.20130711) unstable; urgency=low
[ikiwiki.git] / doc / todo / mdwn_preview.mdwn
1 ikiwiki needs a wysiwyg markdown editor. While there have been tries using
2 WMD etc, they are not fully satisfactory, and also the license of
3 everything around WMD is [[unclear|plugins/wmd/discussion]].
4
5 [Hallo](https://github.com/bergie/hallo) is the closest to a solution
6 I've seen.
7 The user can edit the page by clicking on the html part they want to change
8 and typing. Selecting text pops up a toolbar to modify it.
9
10 [Demo of Hallo with live WYSIWYG markdown editing](http://bergie.github.com/hallo/markdown.html)
11 This demo uses showdown, and I still don't know what the license of
12 showdown is. However, the showdown part seems to only be to handle the live
13 conversion from the markdown source in the edit field to the html. The 
14 (edited) html to markdown conversion is accomplished by Hallo.
15
16 So, ikiwiki could use this in a page edit UI that does not show the
17 markdown at all. The user would edit the live page, entirely in wysiwyg
18 mode, and on saving hallo's generated markdown would be saved. Probably
19 there would need to be a button to bring up the current markdown editor
20 too, but without showdown, changes in it would not immediatly preview, so
21 it'd make sense to disable hallo when the editor is visible.
22
23 Issue: Ikiwiki directives can generate html. We would not want that html to
24 be editable by halo and converted back to markdown. Also, the directives
25 need to appear in the html so users can edit them. This seems to call for a
26 special page rendering mode for editing, in which directives are either not
27 expanded, or are expanded but the generated html wrapped in some tag that
28 makes hallo refuse to edit it (which would probably require that feature be
29 added to hallo, currently it acts on all blocks with `class=editable`),
30 or otherwise allows it to be stripped out at save time. --[[Joey]]
31
32 ### old discussion
33
34
35 The [StackOverflow](http://stackoverflow.com/) site uses markdown for markup.
36 It has a fancy javascript thing for showing a real-time preview of what the user
37 is editing. It would be nice if ikiwiki could support this, too. The thing they
38 use on StackOverflow is supposed to be free software, so it should be easy to
39 add to ikiwiki.
40
41 > See [[wikiwyg]]. Note that I do not have a copy of the code for that, or
42 > it'd be in ikiwiki already. --[[Joey]] 
43
44 >> I just had a brief look at the [[wikiwyg]] page and the link to the plugin was
45 >> broken.  The StackOverflow site uses the [WMD](http://wmd-editor.com/) editor,
46 >> which seems to be related to the [ShowDown](http://attacklab.net/showdown/)
47 >> javascript port of Markdown.  Interestingly, [WMD source](http://wmd.googlecode.com/)
48 >> is now available under an MIT license, though it is supposedly undergoing heavy
49 >> refactoring.  It looks like there was previous discussion ( [[todo/Add_showdown_GUI_input__47__edit]] )
50 >> about a showdown plugin.  Maybe a WMD plugin would be worthwhile.  I might
51 >> look into it if I have time on the weekend. -- [[Will]]
52
53 [[!tag wishlist]]
54
55 >>> Below is a simple plugin/[[patch]] to make use of the WMD editor.
56
57 >>>> Now added to ikiwiki, thanks! --[[Joey]] 
58
59 >>> Turns out it isn't hard at all to
60 >>> get a basic version going (which doesn't handle directives at all, nor does it swtich itself off when you're
61 >>> editing something other than Markdown source).  I've
62 >>> removed the done tag so this is visible as a patch. -- [[Will]]
63
64 >>>> Hmm, it would be good if it turned off for !mdwn. Although this could
65 >>>> be difficult for a new page, since there is a dropdown selector to
66 >>>> choose the markup language then. But it should be doable for editing an
67 >>>> existing page.
68
69 >>>>> I agree.  I'm working on this for for both new pages and existing pages.
70 >>>>> It shouldn't be hard once I get WMD going through the javascript API.
71 >>>>> At the moment that is inexplicably failing, and I haven't had time to have a good look at why.
72 >>>>> I may not get a chance to look at this again for a few weeks.
73
74 >>>> Can I get a license statement (ie, GPL-2+) ffrom you for the plugin?
75 >>>> --[[Joey]] 
76
77 >>>>> Certainly.  You're free to use the code I posted below under the GPL-2+ license.  You'll note
78 >>>>> however that I haven't said anything about the WMD code itself.  The WMD web page says:
79
80 >>>>>> "I'm refactoring the code, and will be releasing WMD under the MIT license soon. For now you can download the most recent release (wmd-1.0.1.zip) and use it freely."
81
82 >>>>> It might be best to contact <support@attacklab.net> to for an explicit license on that if you want to include it.
83 >>>>> -- [[Will]]
84
85 > So, I wonder if I should add a copy of the WMD source to ikiwiki, or rely
86 > on the user or distribution providing it. It does not seem to be packaged
87 > for Debian yet. Hmm, I also can't find any copyright or license info in
88 > the zip file. --[[Joey]] 
89
90 >> This is a good question.  My thought is that it will probably not be packaged any time soon,
91 >> so you're better off adding it to IkiWiki.  I'd contact the author of WMD and ask them.  They
92 >> may have more insight.  -- [[Will]]
93
94 Note that the WMD plugin does **not** handle directives.  For this reason the normal `preview` button
95 remains.  Some CSS to clean up the display of the live WMD preview would be good.
96
97 > Can you elucidate the CSS comment -- or will it be obvious what you mean
98 > when I try it? Is it what's needed for the live preview? --[[Joey]]
99
100 >> In the version of the plugin below, a new `div` is added just below the form.  WMD
101 >> populates this div with the HTML it generates from the Markdown source.  This is not very
102 >> pretty at the moment - it appears in the same place as the preview used to, but with no
103 >> header or anything.  Any standard IkiWiki preview will appear below the WMD live preview.
104 >> I recommend having a look at <http://wmd-editor.com/examples/splitscreen>
105 >> for what a little CSS could achieve.  -- [[Will]]
106
107 > Hmm, now that I've tried it, I notice that it does live preview by
108 > default, below the edit window. Which is nice, but then if I hit the
109 > preview button, I get two previews.. which is confusing. (Also, minor,
110 > but: the live preview is missing the "Page Preview:" header.) --[[Joey]] 
111
112 > I wonder how annoying it would be to add some kind of simplistic wikilink
113 > support to wmd's preview? And/or a wikilink button? While not supporting
114 > directies is fine, not supporting wikilinks in a wiki seems a bit
115 > lacking. It may also entice novide users to not use wikilinks and instead
116 > use the hyperlinks that wmd does support. --[[Joey]] 
117
118 > Bug: When I preview, all the text in the edit field seems to be
119 > converted from mdwn to html. I think that wmd is converting the mdwn
120 > into html when the form is posted, so it would also save like that.
121 > I assume that is designed for websites that do not use markdown
122 > internally. Doesn't it have a setting to leave it as markdown?
123 >> Found setting, fixed. --[[Joey]] 
124
125 >>> As I noted above, I've been working on the non-markdown page issue.
126 >>> Below is my a new javascript file that I'm using, and below that a patch
127 >>> to enable it.  This patch makes the normal usage prettier - you get
128 >>> a side panel with the live preview in it.  It also adds a new config
129 >>> option, `wmd_use101api`, which turns on code that tries to use the
130 >>> wmd api.  At the moment this code doesn't seem to work - moreover the
131 >>> code that uses the new API dies early, so any code after that point is
132 >>> completely untested.  I will not
133 >>> get a chance to look at this again soon though, so I thought I'd post
134 >>> my progress so far.  -- [[Will]]
135
136
137 Place the following file in `underlays/wmd/wmd-ikiwiki.js`.
138
139 ----
140
141     // This is some code to interface the WMD interface 1.0.1 with IkiWiki
142     // The WMD interface is planned to change, so this file will likely need
143     // updating in future.
144     
145     if (useWMDinterface) {
146         wmd_options = { autostart: false, output: "Markdown" };
147         var instance = null;
148     
149         hook("onload", initwmd);
150     } else {
151         var typeSelector = document.getElementById("type");
152         
153         var currentType = getType(typeSelector);
154         
155         if (currentType == "mdwn") {
156                 wmd_options = { output: "Markdown" };
157                 document.getElementById("wmd-preview-container").style.display = 'none';
158         } else {
159                 wmd_options = { autostart: false };
160                 document.getElementById("wmd-preview-container").style.display = 'block';
161         }
162     }
163     
164     function initwmd() {
165         if (!Attacklab || !Attacklab.wmd) {
166                 alert("WMD hasn't finished loading!");
167                 return;
168         }
169         
170         var typeSelector = document.getElementById("type");
171         
172         var currentType = getType(typeSelector);
173         
174         if (currentType == "mdwn") {
175                 window.setTimeout(enableWMD,10);
176         }
177         
178         typeSelector.onchange=function() {
179                 var docType=getType(this);
180                 
181                 if (docType=="mdwn") {
182                         enableWMD();
183                 } else {
184                         disableWMD();
185                 }
186         }
187     }
188     
189     function getType(typeSelector)
190     {
191         if (typeSelector.nodeName.toLowerCase() == 'input') {
192                 return typeSelector.getAttribute('value');
193         } else if (typeSelector.nodeName.toLowerCase() == 'select') {
194                 return typeSelector.value;
195                 // return typeSelector.options[typeSelector.selectedIndex].innerText;
196         }
197         return "";
198     }
199     
200     function enableWMD()
201     {
202         var editContent = document.getElementById("editcontent");
203         var previewDiv = document.getElementById("wmd-preview");
204         var previewDivContainer = document.getElementById("wmd-preview-container");
205         
206         previewDivContainer.style.display = 'block';
207         // editContent.style.width = previewDivContainer.style.width;
208         
209         /***** build the preview manager *****/
210         var panes = {input:editContent, preview:previewDiv, output:null};
211         var previewManager = new Attacklab.wmd.previewManager(panes);
212     
213         /***** build the editor and tell it to refresh the preview after commands *****/
214         var editor = new Attacklab.wmd.editor(editContent,previewManager.refresh);
215     
216         // save everything so we can destroy it all later
217         instance = {ta:editContent, div:previewDiv, ed:editor, pm:previewManager};
218     }
219     
220     function disableWMD()
221     {
222         document.getElementById("wmd-preview-container").style.display = 'none';
223     
224         if (instance != null) {
225                 instance.pm.destroy();
226                 instance.ed.destroy();
227                 // inst.ta.style.width='100%'
228         }
229         instance = null;
230     }
231
232
233 ----
234
235     diff --git a/IkiWiki/Plugin/wmd.pm b/IkiWiki/Plugin/wmd.pm
236     index 9ddd237..743a0b8 100644
237     --- a/IkiWiki/Plugin/wmd.pm
238     +++ b/IkiWiki/Plugin/wmd.pm
239     @@ -17,6 +17,13 @@ sub getsetup () {
240         return
241                 plugin => {
242                         safe => 1,
243     +                   rebuild => 1,
244     +           },
245     +           wmd_use101api => {
246     +                   type => "boolean",
247     +                   description => "Use the advanced, but unstable, WMD api for markdown preview.",
248     +                   safe => 0,
249     +                   rebuild => 0,
250                 },
251      }
252      
253     @@ -24,29 +31,25 @@ sub formbuilder_setup (@) {
254         my %params=@_;
255         my $form=$params{form};
256      
257     -   return if ! defined $form->field("do");
258     +   return unless defined $form->field("do");
259         
260         return unless $form->field("do") eq "edit" ||
261     -                   $form->field("do") eq "create" ||
262     -                   $form->field("do") eq "comment";
263     -
264     -   $form->tmpl_param("wmd_preview", "<div class=\"wmd-preview\"></div>\n".
265     -           include_javascript(undef, 1));
266     -}
267     -
268     -sub include_javascript ($;$) {
269     -   my $page=shift;
270     -   my $absolute=shift;
271     -
272     -   my $wmdjs=urlto("wmd/wmd.js", $page, $absolute);
273     -   return <<"EOF"
274     -<script type="text/javascript">
275     -wmd_options = {
276     -   output: "Markdown"
277     -};
278     -</script>
279     -<script src="$wmdjs" type="text/javascript"></script>
280     -EOF
281     +                           $form->field("do") eq "create" ||
282     +                           $form->field("do") eq "comment";
283     +
284     +   my $useAPI = $config{wmd_use101api}?'true':'false';
285     +   my $ikiwikijs = urlto("ikiwiki.js", undef, 1);
286     +   my $wmdIkiwikijs = urlto("wmd-ikiwiki.js", undef, 1);
287     +   my $wmdjs = urlto("wmd.js", undef, 1);
288     +
289     +   my $previewScripts = <<"EOS";
290     +           <script type="text/javascript">useWMDinterface=$useAPI;</script>
291     +           <script src="$ikiwikijs" type="text/javascript"></script>
292     +           <script src="$wmdIkiwikijs" type="text/javascript"></script>
293     +           <script src="$wmdjs" type="text/javascript"></script>
294     +EOS
295     +
296     +   $form->tmpl_param("wmd_preview", $previewScripts);
297      }
298      
299      1
300     diff --git a/doc/style.css b/doc/style.css
301     index a6e6734..36c2b13
302     --- a/doc/style.css
303     +++ b/doc/style.css
304     @@ -76,9 +76,16 @@ div.tags {
305         float: right;
306      }
307      
308     +/*
309      #editcontent {
310         width: 100%;
311      }
312     +*/
313     +
314     +#wmd-preview-container {
315     +   width: 49%;
316     +   float: right;
317     +}
318      
319      img {
320         border-style: none;
321     diff --git a/templates/editpage.tmpl b/templates/editpage.tmpl
322     index b1cf015..1d2f080 100644
323     --- a/templates/editpage.tmpl
324     +++ b/templates/editpage.tmpl
325     @@ -15,6 +15,14 @@ Page type: <TMPL_VAR FIELD-TYPE>
326      <TMPL_VAR FIELD-PAGE>
327      <TMPL_VAR FIELD-TYPE>
328      </TMPL_IF>
329     +<TMPL_IF NAME="WMD_PREVIEW">
330     +<div id="wmd-preview-container">
331     +<div  class="header">
332     +<span>Live preview:</span>
333     +</div>
334     +<div class="wmd-preview" id="wmd-preview"></div>
335     +</div>
336     +</TMPL_IF>
337      <TMPL_VAR FIELD-EDITCONTENT><br />
338      <TMPL_IF NAME="CAN_COMMIT">
339      Optional comment about this change:<br />