+sub getsetup () {
+ return
+ plugin =>
+ { safe => 1
+ , rebuild => undef
+ , section => "widget"
+ };
+ }
+my $params_re
+ = qr{
+ (?>
+ (?>(?:[^\[\]]|\[[^\[]|\][^\]])+)
+ |
+ (?'loop'
+ \[\[
+ (?>
+ (?>(?:[^\[\]]|\[[^\[]|\][^\]])+)
+ |
+ (?&loop)
+ )*
+ \]\]
+ )
+ )*
+ }x;
+sub scan (@) {
+ my %params = @_;
+ my $content = $params{content};
+ my $prefix = $config{prefix_directives} ? "!poll" : "poll";
+ my $type = IkiWiki::pagetype($pagesources{$params{page}});
+ if (defined $type and $type eq "mdwn") {
+ my %polls = ();
+ while ($content =~ m{(\\?)\[\[\Q$prefix\E(\s+id="([^"]*)")?\s+($params_re)\s*\]\]}gs) {
+ my ($escape, $poll, $directive) = ($1, $3, $4);
+ next if $escape;
+ $poll = '' unless defined $poll;
+ error("poll id=`$poll' must match (|[a-z][a-z0-9_-]*) on page=`$params{page}'")
+ unless $poll =~ m/^(|[a-z][a-z0-9_-]*)$/;
+ my %poll = ();
+ my $userdir = defined $config{userdir} ? $config{userdir}.'/' : '';
+ while ($directive =~ m/(^|\s+)(\d+)(="([^"]*)")?\s+"?([^"]*)"?/gs) {
+ my ($unknown_votes, $known_votes, $choice) = ($2, $4, $5);
+ my @known_votes = defined $known_votes ? grep {length $_ > 0} (split(/\s+/, $known_votes)) : ();
+ $poll{$choice} =
+ { unknown_votes => $unknown_votes
+ , known_votes => \@known_votes
+ };
+ foreach my $user (@known_votes) {
+ my $userpage_best = bestlink($params{page}, $user);
+ $userpage_best = (length $userpage_best > 0 ? $userpage_best : bestlink($userdir, $user));
+ $userpage_best = (length $userpage_best > 0 ? $userpage_best : ($user =~ m{/} ? '/' : $userdir).$user);
+ add_link($params{page}, $userpage_best);
+ }
+ }
+ error("poll id=`$poll' already exists on page=`$params{page}'")
+ if exists $polls{$poll};
+ $polls{$poll} = \%poll;
+ }
+ $IkiWiki::pagestate{$params{page}}{poll} = \%polls;
+ }
+ }