#!/usr/bin/env perl use 5.012; use strict; use warnings; use JSON; use IPC::Open2; 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); return do { local $/; <OUT> }; } sub add { return unless %last_option; if (defined $last_option{"comment"}) { $last_option{"comment"} = md($last_option{"comment"}); } push(@options, {%last_option}); } while (<>) { chomp; if (/^.$/) { add(); die "end of block without a question at line $.\n" unless defined $question; my %ent = ( "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; $source = $3; chomp $source if $source; } 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"} .= "$_\n"; } } say (to_json [@questions]);