Quick actions

cmd+k|ctrl+k

Navigation

Languages

Untitled

Snippet info

Language

Raku

Visibility

unlisted

Author

legacy-anonymous

Created

2026-06-05T05:59:03.020966Z

Updated

2026-06-05T05:59:03.020966Z

#!/usr/bin/env raku

grammar TinyMD {
    token TOP        { \s* <block>* \s* }
    token block      { <hr> || <header> || <codeblock> || <quote> || <ul> || <ol> || <para> }
    token hr         { \h* <[-*_]> ** 3..* \h* \n+ }
    token header     { $<lvl>=('#' ** 1..6) \h+ $<text>=\N+ \n* }
    token codeblock  { [ [ ' ' ** 4 | \t ] $<text>=\N+ \n* ]+ }
    token quote      { [ \h* '>' \h* $<text>=\N+ \n* ]+ }
    token ul         { [ \h* <[-*+]> \h+ $<text>=\N+ \n* ]+ }
    token ol         { [ \h* \d+ '.' \h+ $<text>=\N+ \n* ]+ }
    token block_stop { \h* [ <[-*_#]> | \d+ '.' | '>' | '    ' | \t ] }
    token para       { [ <!before <block_stop> > $<text>=\N+ \n* ]+ }
}

class MD-HTML {
    method TOP($/) { make $<block>.map(*.made).join("\n\n") }
    method block($/) {
        make ($<hr> || $<header> || $<codeblock> || $<quote> || $<ul> || $<ol> || $<para>).made;
    }
    method hr($/)        { make "<hr>" }
    method header($/)    { make "<h{$<lvl>.chars}>" ~ inline($<text>.Str) ~ "</h{$<lvl>.chars}>" }
    method codeblock($/) { make "<pre><code>\n" ~ $<text>.join("\n") ~ "\n</code></pre>" }
    method quote($/)     { make "<blockquote>\n" ~ $<text>.map({"  <p>"~inline($_)~"</p>"}).join("\n") ~ "\n</blockquote>" }
    method para($/)      { make "<p>\n  " ~ inline($<text>.join("\n")) ~ "\n</p>" }
    method ul($/)        { make "<ul>\n" ~ $<text>.map({"  <li>" ~ inline($_) ~ "</li>"}).join("\n") ~ "\n</ul>" }
    method ol($/)        { make "<ol>\n" ~ $<text>.map({"  <li>" ~ inline($_) ~ "</li>"}).join("\n") ~ "\n</ol>" }
    sub inline($str) {
        $str.subst(/ \! \[ (.*?) \] \( (.*?) \) /,    -> $/ { qq|<img src="$1" alt="$0">| }, :g) # Images
            .subst(/ \[ (.*?) \] \( (.*?) \) /,       -> $/ { qq|<a href="$1">{$0}</a>| },   :g) # Links
            .subst(/ \*\* (.*?) \*\* | __ (.*?) __ /, -> $/ { "<strong>{ $0 || $1 }</strong>" }, :g) # bold
            .subst(/ \* (.*?) \* | _ (.*?) _ /,       -> $/ { "<em>{ $0 || $1 }</em>" },     :g) # italic
            .subst(/ \` (.*?) \` /,                   -> $/ { "<code>{$0}</code>" },         :g) # code
    }
}

my $markdown = q:to/END/;
# Markdown Core Support

This is a paragraph with a [link](https://raku.org) and an ![image](logo.png).
It supports **bold**, __bold__, *italics*, _italics_, and `code`.

---

> This is a blockquote.
> It can span multiple lines!

1. First ordered item
2. Second ordered item

* Unordered item A
- Unordered item B

    print("This is a code block");
    say "Because it is indented by 4 spaces";
END

say TinyMD.parse($markdown, actions => MD-HTML.new).made;
INFO