=begin pod

=head1 NAME

App::Rak::Markdown - convert App::Rak output to Markdown

=head1 SYNOPSIS

=begin code :lang<raku>
use App::Rak::Markdown;

my $rmd = App::Rak::Markdown.new;

spurt "result.md", $rmd.markdown(@output);

spurt "result.md", $rmd.run(<--unicode §love>, :tableize<unicode>);
=end code

=head1 DESCRIPTION

The C<App::Rak::Markdown> distribution provides logic to convert the
output of L<C<App::Rak>|https://raku.land/zef:lizmat/App::Rak> to
Markdown format.

This can either be done from captured output, or from a set of arguments
to be sent to the C<rak> command line script.

Its main use is to create markdown gists of search results, such as
for the C<rakkable|https://raku.land/zef:lizmat/IRC::Client::Plugin::Rakkable>
IRC bot.

=head1 METHODS

=head2 new

=begin code :lang<raku>
my $rmd = App::Rak::Markdown.new(
  break => '§§§',  # default: '***'
);
=end code

The C<new> method takes 1 named argument:

=head3 :break

The string to be used / checked for between grouped items in C<rak>'s
output (as documented with the C<--break> argument).  Defaults to
C<"***">.

=head2 markdown

=begin code :lang<raku>
say $rmd.markdown(@output);

my $markdown = $rmd.markdown(
  @output,
  :$items,    # store # of items seen, default: don't bother
  :$files,    # store # of files seen, default: don't bother
  :$heads,    # store # of headers seen, default: don't bother
  :headers(0),  # how many levels of headers, default: 1
  :depth<##>,   # markdown string of top headers, default: "###"
  :&tableizer,  # logic to create tables, default: none
  :&splitter,   # headers split logic, default: *.split("/",$headers)
)
=end code

The C<markdown> method takes one positional argument and an optional
number of named arguments, and returns a string formatted according
to Markdown rules.

It takes one positional argument: a list of lines of C<rak> output.

It also takes the following optional named arguments:
=item :$items - where to store the # of items seen, default: don't bother
=item :$files - where to store the # of files seen, default: don't bother
=item :$heads - where to store the # of headers seen, default: don't bother
=item :headers - the number of header levels, defaults to 1
=item :depth - the markdown string for the top header, default "###"
=item :tableizer - logic to create tables, default: none.
=item :splitter - headers split logic, default: *.split("/",$headers)

=head3 Creating tables

If the output from C<rak> is fit to create markdown tables for (e.g.
the C<--unicode> option, the C<:tableizer> named argument can be used
to indicate a C<Callable> that will be called to manage creating
markdown tables.

This C<Callable> is expected to be called without any arguments: in that
case it should return B<two> lists: the first with the names of the
columns, and the second with formatting info for each column.  The
formatting info can be specified with the following words:
=item left - align text in column to the left
=item center - center text in colum
=item right - align text in column to the right

Any other word will cause no specific aligning to be done. 

If called B<with> an argument, it should return a list with the text
for each column.

Some standard rak options have a dedicated tableizer, which can be
invoked by name.  They currently are:
=item unicode - tableize for --unicode output
=item frequencies - tableize for --frequencies output
=item unique - tableize for --unique output

=head2 run

=begin code :lang<raku>
say "result.md", $rmd.run(<--unicode §love>, :tableize<unicode>);
=end code

=begin output
hex | name | graph
:- | :-: | :-:
1F3E9 | <b>LOVE</b> HOTEL | 🏩
1F48C | <b>LOVE</b> LETTER | 💌
1F91F | I <b>LOVE</b> YOU HAND SIGN | 🤟
=end output

The C<run> method is effectively a wrapper around the C<markdown> method.

It either returns the Markdown string, or C<Nil> if something went wrong,
or if not enough lines were received from C<rak> to make parsing to
Markdown worthwhile.

The positional argument is required: it should contain the arguments
to be sent to C<rak>.

These named arguments can be specified with the C<run> method:
=item :@out - where to store output of rak, default: don't bother
=item :@err - where to store error output of rak, default: don't bother
=item :min-lines - the minumum number of lines in output, default: 0
=item :sort(Callable?) - sort the rak output before calling .markdown

Note that the C<:@out> named argument only makes sense if the
C<:min-lines> argument also has been specified with a value greater
than 0.

All other named arguments that C<markdown> can receive, can also be
specified here and will be passed on to the C<markdown> method:
=item :$items - where to store the # of items seen, default: don't bother
=item :$files - where to store the # of files seen, default: don't bother
=item :$heads - where to store the # of headers seen, default: don't bother
=item :headers - the number of header levels, defaults to 1
=item :depth - the markdown string for the top header, default "###"
=item :tableizer - logic to create tables, default: none.
=item :splitter - headers split logic, default: *.split("/",$headers)

=head1 AUTHOR

Elizabeth Mattijsen <liz@raku.rocks>

Source can be located at: https://github.com/lizmat/App-Rak-Markdown .
Comments and Pull Requests are welcome.

If you like this module, or what I'm doing more generally, committing to a
L<small sponsorship|https://github.com/sponsors/lizmat/>  would mean a great
deal to me!

=head1 COPYRIGHT AND LICENSE

Copyright 2025, 2026 Elizabeth Mattijsen

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

=end pod
