hook(type => "getsetup", id => 'comments', call => \&getsetup);
hook(type => "preprocess", id => 'comments', call => \&preprocess);
hook(type => "sessioncgi", id => 'comment', call => \&sessioncgi);
- hook(type => "htmlize", id => "_comment",
- call => \&IkiWiki::Plugin::mdwn::htmlize);
+ hook(type => "htmlize", id => "_comment", call => \&htmlize);
+ hook(type => "pagetemplate", id => "comments", call => \&pagetemplate);
IkiWiki::loadplugin("inline");
IkiWiki::loadplugin("mdwn");
} # }}}
sub htmlize { # {{{
- eval { use IkiWiki::Plugin::mdwn; };
+ eval q{use IkiWiki::Plugin::mdwn};
error($@) if ($@);
return IkiWiki::Plugin::mdwn::htmlize(@_)
} # }}}
return
plugin => {
safe => 1,
+ rebuild => 1,
+ },
+ # Pages where comments are shown, but new comments are not
+ # allowed, will show "Comments are closed".
+ comments_shown_pagespec => {
+ type => 'pagespec',
+ example => 'blog/*',
+ default => '',
+ description => 'PageSpec for pages where comments will be shown inline',
+ link => 'ikiwiki/PageSpec',
+ safe => 1,
+ rebuild => 1,
+ },
+ comments_open_pagespec => {
+ type => 'pagespec',
+ example => 'blog/* and created_after(close_old_comments)',
+ default => '',
+ description => 'PageSpec for pages where new comments can be posted',
+ link => 'ikiwiki/PageSpec',
+ safe => 1,
+ rebuild => 1,
+ },
+ comments_pagename => {
+ type => 'string',
+ example => 'comment_',
+ default => 'comment_',
+ description => 'Base name for comments, e.g. "comment_" for pages like "sandbox/comment_12"',
+ safe => 0, # manual page moving will required
rebuild => undef,
},
+ comments_allowdirectives => {
+ type => 'boolean',
+ default => 0,
+ example => 0,
+ description => 'Allow directives in newly posted comments?',
+ safe => 1,
+ rebuild => 0,
+ },
+ comments_commit => {
+ type => 'boolean',
+ example => 1,
+ default => 1,
+ description => 'commit comments to the VCS',
+ # old uncommitted comments are likely to cause
+ # confusion if this is changed
+ safe => 0,
+ rebuild => 0,
+ },
} #}}}
# Somewhat based on IkiWiki::Plugin::inline blog posting support
sub preprocess (@) { #{{{
my %params=@_;
- unless (length $config{cgiurl}) {
- error(gettext("[[!comments plugin requires CGI enabled]]"));
- }
+ return "";
my $page = $params{page};
$pagestate{$page}{comments}{comments} = defined $params{closed}
? (not IkiWiki::yesno($params{closed}))
: 1;
- $pagestate{$page}{comments}{allowhtml} = IkiWiki::yesno($params{allowhtml});
$pagestate{$page}{comments}{allowdirectives} = IkiWiki::yesno($params{allowdirectives});
$pagestate{$page}{comments}{commit} = defined $params{commit}
? IkiWiki::yesno($params{commit})
debug("page $params{page} => destpage $params{destpage}");
- my $posts = '';
unless (defined $params{inline} && !IkiWiki::yesno($params{inline})) {
- eval { use IkiWiki::Plugin::inline; };
+ my $posts = '';
+ eval q{use IkiWiki::Plugin::inline};
error($@) if ($@);
my @args = (
pages => "internal($params{page}/_comment_*)",
push @args, feedshow => $params{feedshow} if defined $params{feedshow};
push @args, timeformat => $params{timeformat} if defined $params{timeformat};
push @args, feedonly => $params{feedonly} if defined $params{feedonly};
- $posts = "\n" . IkiWiki::preprocess_inline(@args);
+ $posts = IkiWiki::preprocess_inline(@args);
+ $formtemplate->param("comments" => $posts);
}
- return $formtemplate->output . $posts;
+ return $formtemplate->output;
} # }}}
# FIXME: logic taken from editpage, should be common code?
} # }}}
# FIXME: logic adapted from recentchanges, should be common code?
+# returns (author URL, pretty-printed version)
sub linkuser ($) { # {{{
my $user = shift;
my $oiduser = eval { IkiWiki::openiduser($user) };
}
} # }}}
-# FIXME: taken from IkiWiki::Plugin::editpage, should be common?
-sub checksessionexpiry ($$) { # {{{
- my $session = shift;
- my $sid = shift;
-
- if (defined $session->param("name")) {
- if (! defined $sid || $sid ne $session->id) {
- error(gettext("Your login session has expired."));
- }
- }
-} # }}}
-
# Mostly cargo-culted from IkiWiki::plugin::editpage
sub sessioncgi ($$) { #{{{
my $cgi=shift;
error(gettext("bad page name"));
}
- my $allow_directives = $pagestate{$page}{comments}{allowdirectives};
- my $allow_html = $pagestate{$page}{comments}{allowdirectives};
- my $commit_comments = defined $pagestate{$page}{comments}{commit}
- ? $pagestate{$page}{comments}{commit}
- : 1;
+ my $allow_directives = $config{comments_allowdirectives};
+ my $commit_comments = $config{comments_commit};
+ my $comments_pagename = $config{comments_pagename};
# FIXME: is this right? Or should we be using the candidate subpage
# (whatever that might mean) as the base URL?
htmllink($page, $page, 'ikiwiki/formatting',
noimageinline => 1,
linktext => 'FormattingHelp'),
- allowhtml => $allow_html,
allowdirectives => $allow_directives);
+ if ($form->submitted eq CANCEL) {
+ # bounce back to the page they wanted to comment on, and exit.
+ # CANCEL need not be considered in future
+ IkiWiki::redirect($cgi, urlto($page, undef, 1));
+ exit;
+ }
+
if (not exists $pagesources{$page}) {
error(sprintf(gettext(
"page '%s' doesn't exist, so you can't comment"),
$page));
}
- if (not $pagestate{$page}{comments}{comments}) {
+
+ if (not pagespec_match($page, $config{comments_open_pagespec},
+ location => $page)) {
error(sprintf(gettext(
- "comments are not enabled on page '%s'"),
+ "comments on page '%s' are closed"),
$page));
}
- if ($form->submitted eq CANCEL) {
- # bounce back to the page they wanted to comment on, and exit.
- # CANCEL need not be considered in future
- IkiWiki::redirect($cgi, urlto($page, undef, 1));
- exit;
- }
-
+ IkiWiki::checksessionexpiry($session, $cgi->param('sid'));
IkiWiki::check_canedit($page . "[postcomment]", $cgi, $session);
my ($authorurl, $author) = linkuser(getcgiuser($session));
my $body = $form->field('body') || '';
$body =~ s/\r\n/\n/g;
$body =~ s/\r/\n/g;
- $body = "\n" if $body !~ /\n$/;
+ $body .= "\n" if $body !~ /\n$/;
unless ($allow_directives) {
# don't allow new-style directives at all
- $body =~ s/(^|[^\\])\[\[!/$1\\[[!/g;
+ $body =~ s/(^|[^\\])\[\[!/$1[[!/g;
# don't allow [[ unless it begins an old-style
# wikilink, if prefix_directives is off
- $body =~ s/(^|[^\\])\[\[(?![^\n\s\]+]\]\])/$1\\[[!/g
+ $body =~ s/(^|[^\\])\[\[(?![^\n\s\]+]\]\])/$1[[!/g
unless $config{prefix_directives};
}
- unless ($allow_html) {
- $body =~ s/&(\w|#)/&$1/g;
- $body =~ s/</</g;
- $body =~ s/>/>/g;
- }
+ # FIXME: check that the wiki is locked right now, because
+ # if it's not, there are mad race conditions!
+
+ # FIXME: rather a simplistic way to make the comments...
+ my $i = 0;
+ my $file;
+ my $location;
+ do {
+ $i++;
+ $location = "$page/${comments_pagename}${i}";
+ } while (-e "$config{srcdir}/$location._comment");
+
+ my $anchor = "${comments_pagename}${i}";
+
+ IkiWiki::run_hooks(sanitize => sub {
+ $body=shift->(
+ page => $location,
+ destpage => $location,
+ content => $body,
+ );
+ });
# In this template, the [[!meta]] directives should stay at the end,
# so that they will override anything the user specifies. (For
$content_tmpl->param(authorurl => $authorurl);
$content_tmpl->param(subject => $form->field('subject'));
$content_tmpl->param(body => $body);
+ $content_tmpl->param(anchor => "$anchor");
+ $content_tmpl->param(permalink => "$baseurl#$anchor");
my $content = $content_tmpl->output;
# - this means that if they do, rocks fall and everyone dies
if ($form->submitted eq PREVIEW) {
- # $fake is a location that has the same number of slashes
- # as the eventual location of this comment.
- my $fake = "$page/_comments_hypothetical";
- my $preview = IkiWiki::htmlize($fake, $page, 'mdwn',
+ my $preview = IkiWiki::htmlize($location, $page, 'mdwn',
IkiWiki::linkify($page, $page,
IkiWiki::preprocess($page, $page,
- IkiWiki::filter($fake, $page,
- $content),
+ IkiWiki::filter($location,
+ $page, $content),
0, 1)));
IkiWiki::run_hooks(format => sub {
$preview = shift->(page => $page,
}
if ($form->submitted eq POST_COMMENT && $form->validate) {
- # Let's get posting. We don't check_canedit here because
- # that somewhat defeats the point of this plugin.
-
- checksessionexpiry($session, $cgi->param('sid'));
-
- # FIXME: check that the wiki is locked right now, because
- # if it's not, there are mad race conditions!
-
- # FIXME: rather a simplistic way to make the comments...
- my $i = 0;
- my $file;
- do {
- $i++;
- $file = "$page/_comment_${i}._comment";
- } while (-e "$config{srcdir}/$file");
+ my $file = "$location._comment";
# FIXME: could probably do some sort of graceful retry
- # if I could be bothered
+ # on error? Would require significant unwinding though
writefile($file, $config{srcdir}, $content);
my $conflict;
my $message = gettext("Added a comment");
if (defined $form->field('subject') &&
length $form->field('subject')) {
- $message .= ": ".$form->field('subject');
+ $message = sprintf(
+ gettext("Added a comment: %s"),
+ $form->field('subject'));
}
IkiWiki::rcs_add($file);
error($conflict) if defined $conflict;
# Bounce back to where we were, but defeat broken caches
- my $anticache = "?updated=$page/_comment_$i";
+ my $anticache = "?updated=$page/${comments_pagename}${i}";
IkiWiki::redirect($cgi, urlto($page, undef, 1).$anticache);
}
else {
exit;
} #}}}
+sub pagetemplate (@) { #{{{
+ my %params = @_;
+
+ my $page = $params{page};
+ my $template = $params{template};
+
+ if ($template->query(name => 'comments')) {
+ my $comments = undef;
+
+ if (defined $comments && length $comments) {
+ $template->param(name => $comments);
+ }
+ }
+} # }}}
+
package IkiWiki::PageSpec;
sub match_postcomment ($$;@) {