#!/usr/bin/env perl use 5.012; use strict; use warnings; use JSON; use IPC::Open2; use Digest::MD5 qw(md5_base64); my @hlwords = qw/immer nie jede jedem jedes muss keine alle nicht/; my @markdown = qw/cmark --smart --safe/; my $question; my $single_choice; my $source; my $media; my %last_option; my @options; my @questions = (); sub md { # pipe through $markdown my ($input) = @_; my $pid = open2(\*OUT, \*IN, @markdown) or die "open2() failed $!"; print IN $input; close(IN); waitpid($pid, 0); my $html = do { local $/; <OUT> }; my $match = join("|", @hlwords); $html =~ s!\b($match)\b!<span class="hl">$1</span>!; return $html; } sub add { return unless %last_option; if ($last_option{"comment"}) { $last_option{"comment"} = md($last_option{"comment"}); } push(@options, {%last_option}); } while (<>) { if (/^\s*#/) { # ignore comments } elsif (/^\.$/) { add(); die "end of block without a question at line $ARGV:$.\n" unless defined $question; my $any = 0; foreach my $opt (@options) { $opt->{"option"} = md($opt->{"option"}) if $opt->{"option"}; $any = 1 if (not (defined $opt->{"correct"})) or ($opt->{"correct"} eq JSON::true); } die "no correct option at \"$question\" ($ARGV)\n" if not($any) and $single_choice; my %ent = ( "id" => md5_base64($ARGV . $question), "question" => md($question), "options" => [@options], "multiple" => ($single_choice eq "0" ? \0 : \1) ); $ent{"source"} = $source if defined $source; $ent{"media"} = $media if defined $media; push(@questions, { %ent }); undef $question; undef $single_choice; undef $source; undef $media; undef %last_option; undef @options; } elsif (/^([01])(.*?)$/) { $single_choice = $1; $question = $2; chomp $question; if ($question =~ /\(([[0-9]{4}-[0-9]{2})\)/) { $source = $1; $question =~ s/\Q($source)\E//; chomp $source; } } elsif (/^[|](.+)/) { if ($last_option{"option"}) { $last_option{"option"} .= $1; } else { $question .= $1; } } elsif (/^@(.*)/) { $media = $1; chomp $media; } elsif (/^([-+?])\s*(.*)/) { add(); %last_option = ( "option" => $2, "correct" => $1 eq "+" ? JSON::true : $1 eq "-" ? JSON::false : JSON::null ); } elsif (/^.*$/) { # non-empty line $last_option{"comment"} .= $_ if %last_option; } } say (to_json [@questions]);