#| Interaction with pandoc unit module Pandoc; use JSON::Fast; sub markdown-title(IO::Path:D $file --> Str:D) is export { # Call into pandoc my $pandoc = run 'pandoc', '-f', 'gfm', '-t', 'JSON', $file, :out, :err; my $output = $pandoc.out.slurp: :close; my $stderr = $pandoc.err.slurp: :close; # Throw an error if pandoc failed if !$pandoc { die "Pandoc exited with {$pandoc.exitcode}\nout: $output\nerr: $stderr"; } # Parse out output from pandoc, we are making an executive decision to trust # pandoc here, so we won't do any error handling for pandoc's output my %parsed = from-json $output; # Extract a list of top level headers from the pandoc output, this should # only have one element in it, but as this is user input, its untrusted and # we need to do some error handling my sub is-header($v) { $v ~~ Associative && $v ~~ "Header" } my @headers = %parsed.grep(&is-header).grep(*[0] == 1); if @headers.elems > 1 { die "More than one top level header in $file"; }; if @headers.elems == 0 { die "No top level headers in $file"; }; # Extract the header and process it into a string my @header = @headers[0][2].flat; my $title = ""; for @header -> $component { next unless $component ~~ Associative; given $component { when "Str" { $title = $title ~ $component; } when "Space" { $title = $title ~ " "; } default { die "Invalid component type: $_"; } } } return $title; }