diff --git a/render.go b/render.go new file mode 100644 index 0000000..0e03978 --- /dev/null +++ b/render.go @@ -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("
\n")
+				ctx = parseCtxPre
+			} else {
+				builder.WriteString("
\n") + ctx = parseCtxNone + } + } else if ctx == parseCtxPre { + builder.WriteString(line) + builder.WriteString("\n") + } else if strings.HasPrefix(line, "*") { + if ctx != parseCtxList { + builder.WriteString("\n") + ctx = parseCtxNone + } else if strings.HasPrefix(line, "###") { + line = line[3:] + line = strings.TrimLeft(line, spacetab) + builder.WriteString("

" + line + "

\n") + } else if strings.HasPrefix(line, "##") { + line = line[2:] + line = strings.TrimLeft(line, spacetab) + builder.WriteString("

" + line + "

\n") + } else if strings.HasPrefix(line, "#") { + line = line[1:] + line = strings.TrimLeft(line, spacetab) + builder.WriteString("

" + line + "

\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("

" + name + "

\n") + } else if strings.HasPrefix(line, ">") { + builder.WriteString("
" + line + "
") + } else { + builder.WriteString("

" + line + "

\n") + } + } + + // Close any opened tags + switch ctx { + case parseCtxPre: + builder.WriteString("\n") + case parseCtxList: + builder.WriteString("\n") + } + return builder.String() +}