Reference and describe my implementation
[ikiwiki.git] / doc / todo / supporting_comments_via_disussion_pages.mdwn
1 I would love to see more traditional support for comments in ikiwiki.   One
2 way would be to structure data on the discussion page in such a way that a
3 "comment" plugin could parse it and yet the discussion page would still be
4 a valid and usable wiki page.
5
6 For example if the discussion page looked like this:
7
8     # Subject of First Comment
9     Posted by [Adam Shand](http://adam.shand.net/) at 10:34PM on 14/04/2007
10
11     Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi consectetuer nunc quis 
12     magna.  Etiam non est eget sapien vulputate varius. Vivamus magna. Sed justo. Donec 
13     pellentesque ultrices urna.
14
15     # Subject of the Second Comment
16     Posted by [Foo Bar](http://foobar.net/) at 11:41PM on 14/04/2007
17
18     Quisque lacinia, lorem eget ornare facilisis, enim eros iaculis felis, id volutpat nibh
19     mauris ut felis. Vestibulum risus nibh, adipiscing volutpat, volutpat et, lacinia ut, 
20     pede. Maecenas dolor. Vivamus feugiat volutpat ligula.
21
22 Each header marks the start of a new comment and the line immediately
23 following is the comments meta data (author, email/url, datestamp).
24 Hopefully you could structure it in such a way that the scope 
25
26 This would allow:
27
28  * A comment plugin to render the comments in "traditional blog" format .  
29  * Possibly even support nesting comments by the header level?
30  * A comment plugin to create a form at the bottom of the page for people to add comments in the appropriate format to the discussion page
31  * Still remain usable and readable by people who work via svn.
32  * When there is ACL support you could mark the discussion page as read only so it could only be updated by the comment plugin (if that's what you wanted)
33
34 Is this simple enough to be sensible?
35
36 -- [[AdamShand]]
37
38 > Well, if it's going to look like a blog, why not store the data the same
39 > way ikiwiki stores blogs, with a separate page per comment? As already
40 > suggested in [[discussion_page_as_blog]] though there are some things to
41 > be worked out also discussed there.
42 > --[[Joey]]
43
44 >> I certainly won't be fussy about how it gets implemented, I was just trying to think of the lightest weight most "wiki" solution.  :-) -- Adam.
45
46 >>> As a side note, the feature described above (having a form not to add a page but to expand it in a formated way) would be useful for other things when the content is short (timetracking, sub-todo list items, etc..) --[[hb]]
47
48 # [[MarceloMagallon]]'s implementation
49
50 I've been looking into this.  I'd like to implement a "blogcomments"
51 plugin.  Looking at the code, I think the way to go is to have a
52 formbuilder_setup hook that uses a different template instead of the
53 standard editpage one.  That template would not display the editcontent
54 field.  The problem that I'm running into is that I need to append the new
55 content to the old one.
56
57 -- [[MarceloMagallon]]
58
59 > Anything I can do to help? --[[Joey]]
60
61 >> Figured it out.  Can you comment on the code below?  Thanks. -- [[MarceloMagallon]]
62
63 So, I have some code, included below.  For some reason that I don't quite get it's not updating the wiki page after a submit.  Maybe it's something silly on my side...
64
65 What I ended up doing is write something like this to the page:
66
67     [[!blogcomment from="""Username""" timestamp="""12345""" subject="""Some text""" text="""the text of the comment"""]]
68
69 Each comment is processed to something like this:
70
71     <div>
72         <dl>
73             <dt>From</dt><dd>Username</dd>
74             <dt>Date</dt><dd>Date (needs fixing)</dd>
75             <dt>Subject</dt><dd>Subject text</dd>
76         </dl>
77
78         <p>Text of the comment...</p>
79     </div>
80
81 .  In this way the comments can be styled using CSS.
82
83 -- [[MarceloMagallon]]
84
85 ## Code
86
87     #!/usr/bin/perl
88     package IkiWiki::Plugin::comments;
89
90     use warnings;
91     use strict;
92     use IkiWiki '1.02';
93
94     sub import { #{{{
95         hook(type => "formbuilder_setup", id => "comments",
96             call => \&formbuilder_setup);
97         hook(type => "preprocess", id => "blogcomment",
98             call => \&preprocess);  
99     } # }}}
100
101     sub formbuilder_setup (@) { #{{{
102         my %params=@_;
103         my $cgi = $params{cgi};
104         my $form = $params{form};   
105         my $session = $params{session};
106
107         my ($page)=$form->field('page');
108         $page=IkiWiki::titlepage(IkiWiki::possibly_foolish_untaint($page));
109
110         # XXX: This needs something to make it blog specific
111         unless ($page =~ m{/discussion$} &&
112                 $cgi->param('do') eq 'edit' &&
113                 ! exists $form->{title})
114         {
115             return;
116         }
117
118         if (! $form->submitted)
119         {
120             $form->template(IkiWiki::template_file("makeblogcomment.tmpl"));
121             $form->field(name => "blogcomment", type => "textarea", rows => 20,
122                 cols => 80);
123             return;
124         }
125
126         my $content="";
127         if (exists $pagesources{$page}) {
128             $content=readfile(srcfile($pagesources{$page}));
129             $content.="\n\n";
130         }
131         my $name=defined $session->param('name') ?
132             $session->param('name') : gettext('Anonymous');
133         my $timestamp=time;
134         my $subject=defined $cgi->param('comments') ?
135             $cgi->param('comments') : '';
136         my $comment=$cgi->param('blogcomment');
137
138         $content.=qq{[[!blogcomment from="""$name""" timestamp="""$timestamp""" subject="""$subject""" text="""$comment"""]]\n\n};
139         $content=~s/\n/\r\n/g;
140         $form->field(name => "editcontent", value => $content, force => 1);
141     } # }}}
142
143     sub preprocess (@) { #{{{
144         my %params=@_;
145
146         my ($text, $date, $from, $subject, $r);
147
148         $text=IkiWiki::preprocess($params{page}, $params{destpage},
149                 IkiWiki::filter($params{page}, $params{text}));
150         $from=exists $params{from} ? $params{from} : gettext("Anonymous");
151         $date=localtime($params{timestamp}) if exists $params{timestamp};
152         $subject=$params{subject} if exists $params{subject};
153
154         $r = qq{<div class="blogcomment"><dl>\n};
155         $r .= '<dt>' . gettext("From") . "</dt><dd>$from</dd>\n" if defined $from;
156         $r .= '<dt>' . gettext("Date") . "</dt><dd>$date</dd>\n" if defined $date;
157         $r .= '<dt>' . gettext("Subject") . "</dt><dd>$subject</dd>\n"
158             if defined $subject;
159         $r .= "</dl>\n" . $text . "</div>\n";
160
161         return $r;
162     } # }}}
163     
164     1;
165
166 # [[smcv]]'s implementation
167
168 I've started a smcvpostcomment plugin (to be renamed to postcomment if people like it, but I'm namespacing it while it's still experimental) which I think more closely resembles what Joey was after. The code is cargo-culted from a mixture of editpage and inline's "make a blog post" support - it has to use a lot of semi-internal IkiWiki:: functions (both of those plugins do too). It doesn't fully work yet, but I'll try to get it into a state where it basically works and can be published in the next week or two.
169
170 My approach is:
171
172 * Comments are intended to be immutable after posting (so, only editable by direct committers), so they go on internal pages (*._comment); these internal pages are checked in to the RCS (although later I might make this optional)
173
174 * ?do=smcvpostcomment (in the CGI script) gives a form that lets logged-in users (later, optionally also anonymous users) create a new comment
175
176 * \[[!smcvpostcomment]] just inserts a "Post comment" button into the current page, which goes to ?do=smcvpostcomment - it's intended to be used in conjunction with an \[[!inline]] that will display the comments
177
178 * The title (subject line), author and authorurl are set with \[[!meta]] directives, just like the way aggregate does it (which means I'll probably have to disallow the use of those \[[!meta]] directives in the body of the comment, to avoid spoofing - obviously, spoofing can be detected by looking at RecentChanges or gitweb, but the expectation for blog-style comments is that the metadata seen in the comment can be trusted)
179
180 * The initial plan is to have comments hard-coded to be in Markdown, with further directives not allowed - I'll relax this when I've worked out what ought to be allowed!
181
182 I've also updated Marcelo's code (above) to current ikiwiki, and moved it to a "marceloblogcomment" namespace - it's in the "marcelocomments" branch of my repository (see <http://git.debian.org/?p=users/smcv/ikiwiki.git;a=log;h=refs/heads/marcelocomments>). I had to reconstitute the .tmpl file, which Marcelo didn't post here.
183
184 --[[smcv]]
185
186 OK, the postcomment branch in my repository contains an implementation. What
187 do you think so far? Known issues include:
188
189 * The combination of RSS/Atom links and the "post new comment..." button is
190   ugly - I need a way to integrate the "new comment" button into the feed links
191   somehow, like the way inline embeds its own "new blog post..." feature
192   (I don't think the current way really scales, though)
193
194 * There are some tweakables (whether to commit comments into the VCS, whether
195   wikilinks are allowed, whether directives are allowed) that are theoretically
196   configurable, but are currently hard-coded
197
198 * The wikilink/directive disarming doesn't work unless you have
199   prefixdirectives set (which I just realised)
200
201 * \[[!smcvpostcomment]] now displays the comments too, by invoking \[[!inline]]
202   with suitable parameters - but it does so in a very ugly way
203
204 * Start-tags in a comment with no corresponding end-tag break page formatting
205   (unless htmltidy is enabled - inline and aggregate have the same problem)
206
207 * There is no access control, so anonymous users can always comment, and so
208   can all logged-in users. Perhaps we need to extend canedit() to support
209   different types of edit? Or perhaps I should ignore canedit() and make the
210   access control configurable via a parameter to \[[!smcvpostcomment]]?
211   I'd like to be able to let anonymous (or at least non-admin) users comment
212   on existing pages, but not edit or create pages (but perhaps I'm being too
213   un-wikiish).
214
215 --[[smcv]]