about summary refs log tree commit diff stats
path: root/ht.awk
blob: a382ae7f4473118d0429a5a42370433e5f2a367c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/awk -f
# HAT TRICK
# (C) 2022 C. Duckworth

# ht.awk converts mostly-html (with some conveniences) to actual html

function bufpush(s) {
    BUF = BUF (BUF ? "\n" : "") s;
}

function buflush() {
    if (BUF) print BUF;
    BUF = "";
    if (tag && (tag != "html") && (tag != "raw"))
        print "</" tag ">";
}

function esc(t) {
    # This is of much more limited utility than I initially realized.
    gsub(/&/, "\\&amp;", t);
    gsub(/</, "\\&lt;", t);
    gsub(/>/, "\\&gt;", t);
    sub(/^ /, "\\&nbsp;", t);
    return t;
}

/^;/ { sub(/^;/,""); print "<!--", esc($0), "-->"; next; }

/^</ { # Raw HTML
    if (! (tag == "html")) tag = "html";
    bufpush($0);
    next;
}

/^```$/ { # Raw block
    if (! (tag == "raw")) {
        tag = "raw";
        getline;
        bufpush("<pre><code>" $0);
    } else {
        bufpush("</code></pre>");
        buflush();
        tag = "";
    }
    next;
}

/^=>/ { # Links (Gemini-style)
    if (tag == "raw") next;
    link = "<a href=\"" esc($2) "\">" $3;
    for (i=4;i<=NF;i++) link = link " " $i;
    link = link "</a>";
    bufpush(link);
    next;
}

/^-/ { # Unordered lists
    if (tag == "raw") next;
    if (! (tag == "ul")) tag = "ul";
    sub(/^-[ \t]*/, "<li>");
}

/^[0-9]+\./ { # Ordered lists
    if (tag == "raw") next;
    if (! (tag == "ol")) tag = "ol";
    sub(/^[0-9]+\.[ \t]/, "<li>");
}

/^>/ { # Blockquotes
    if (tag == "raw") next;
    if (! (tag == "blockquote")) tag = "blockquote";
    sub(/^>[ \t]*/,"");
}

/^#+/ { # Headers
    if (tag == "raw") next;
    match($0, /^#+/);
    if (! (tag == "h" RLENGTH)) {
        buflush();
        tag = "h" RLENGTH;
    }
    sub(/^#+[ \t]*/,"");
}

/^$/ {
    if (tag == "raw") next;
    buflush();
    tag = "";
}

/./ {
    if (! tag) tag = "p";
    if (! BUF) bufpush("<" tag ">");
    if (tag == "raw") $0 = esc($0);
    bufpush($0);
}

END { buflush(); }