Blob


1 #!/usr/bin/env perl
2 #
3 # gem2html - opinionated converter text/gemini to html
4 # public domain
6 use v5.10;
7 use strict;
8 use warnings;
10 use open ":std", ":encoding(UTF-8)";
12 my $in_pre = 0;
13 my $in_list = 0;
15 while (<>) {
16 chomp;
17 if ($in_pre && m/^```/) {
18 $in_pre = 0;
19 say "</pre>";
20 } elsif (!$in_pre && m/^```/) {
21 if ($in_list) {
22 $in_list = 0;
23 say "</ul>";
24 }
25 $in_pre = 1;
26 print "<pre>";
27 } elsif ($in_pre) {
28 say san($_);
29 } elsif ($in_list && m/^$/) {
30 say "</ul>";
31 $in_list = 0;
32 } elsif (m/^\*\s+(.*)/) { # NB: at least one space
33 if (!$in_list) {
34 $in_list = "item";
35 say "<ul>";
36 } elsif ($in_list eq "link") {
37 $in_list = "item";
38 say "</ul>";
39 say "<ul>";
40 }
41 output("li", $1);
42 } elsif (m/^=>\s*([^\s]*)\s*(.*)$/) {
43 if (!$in_list) {
44 $in_list = "link";
45 say "<ul class='link-list'>";
46 } elsif ($in_list eq "item") {
47 $in_list = "link";
48 say "</ul>";
49 say "<ul class='link-list'>";
50 }
51 say "<li><a href='$1'>". san($2 || $1) ."</a></li>";
52 } elsif (m/^###\s*(.*)$/) {
53 output("h3", $1);
54 } elsif (m/^##\s*(.*)$/) {
55 output("h2", $1);
56 } elsif (m/^#\s*(.*)$/) {
57 output("h1", $1);
58 } elsif (m/^>\s*(.*)$/) {
59 output("blockquote", $1);
60 } else {
61 output("p", $_);
62 }
63 }
65 sub san {
66 $_ = shift;
67 s/&/\&amp;/g;
68 s/</\&lt;/g;
69 s/>/\&gt;/g;
70 return $_;
71 }
73 sub output {
74 my ($tn, $content) = @_;
76 if (!$in_list && $tn eq "li") {
77 $in_list = 1;
78 say "<ul>";
79 }
81 if ($in_list && $tn ne "li") {
82 $in_list = 0;
83 say "</ul>";
84 }
86 return if $tn eq "p" && $content eq "";
88 say "<$tn>". san($content) ."</$tn>";
89 }