Add GeminiToHTML renderer

This commit is contained in:
adnano 2020-09-28 22:59:04 -04:00
parent 82a5490ff5
commit 8b811c4e23

89
render.go Normal file
View file

@ -0,0 +1,89 @@
package main
import (
"bufio"
"io"
"strings"
)
// GeminiToHTML reads Gemini from the provided reader and returns an HTML string.
func GeminiToHTML(r io.Reader) string {
const spacetab = " \t"
type parseCtx int
const (
parseCtxNone = iota
parseCtxPre
parseCtxList
)
var builder strings.Builder
var ctx parseCtx
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
if len(line) == 0 {
continue
}
if strings.HasPrefix(line, "```") {
if ctx != parseCtxPre {
builder.WriteString("<pre>\n")
ctx = parseCtxPre
} else {
builder.WriteString("</pre>\n")
ctx = parseCtxNone
}
} else if ctx == parseCtxPre {
builder.WriteString(line)
builder.WriteString("\n")
} else if strings.HasPrefix(line, "*") {
if ctx != parseCtxList {
builder.WriteString("<ul>\n")
ctx = parseCtxList
}
builder.WriteString("<li>")
line = line[1:]
builder.WriteString(strings.TrimLeft(line, spacetab))
builder.WriteString("</li>\n")
} else if ctx == parseCtxList {
builder.WriteString("</ul>\n")
ctx = parseCtxNone
} else if strings.HasPrefix(line, "###") {
line = line[3:]
line = strings.TrimLeft(line, spacetab)
builder.WriteString("<h3>" + line + "</h3>\n")
} else if strings.HasPrefix(line, "##") {
line = line[2:]
line = strings.TrimLeft(line, spacetab)
builder.WriteString("<h2>" + line + "</h2>\n")
} else if strings.HasPrefix(line, "#") {
line = line[1:]
line = strings.TrimLeft(line, spacetab)
builder.WriteString("<h1>" + line + "</h1>\n")
} else if strings.HasPrefix(line, "=>") {
line = line[2:]
line = strings.TrimLeft(line, spacetab)
split := strings.IndexAny(line, spacetab)
url := line[:split]
name := line[split:]
name = strings.TrimLeft(name, spacetab)
builder.WriteString("<p><a href='" + url + "'>" + name + "</a></p>\n")
} else if strings.HasPrefix(line, ">") {
builder.WriteString("<blockquote>" + line + "</blockquote>")
} else {
builder.WriteString("<p>" + line + "</p>\n")
}
}
// Close any opened tags
switch ctx {
case parseCtxPre:
builder.WriteString("</pre>\n")
case parseCtxList:
builder.WriteString("</ul>\n")
}
return builder.String()
}