1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-10-30 11:46:16 +00:00
mycorrhiza/plugin/parser/gemini.go
2020-07-14 18:46:49 +05:00

135 lines
2.7 KiB
Go

package parser
import (
"bufio"
"bytes"
"fmt"
"strings"
"github.com/bouncepaw/mycorrhiza/util"
)
const (
linkToken = "=>"
headerToken = "#"
quoteToken = ">"
preformattedToken = "```"
listItemToken = "*"
)
var preState bool
var listState bool
func GeminiToHtml(gemini []byte) string {
lines, _ := StringToLines(string(util.NormalizeEOL(gemini)))
var html []string
for _, line := range lines {
html = append(html, geminiLineToHtml(line))
}
buffer := bytes.Buffer{}
for _, line := range html {
buffer.WriteString(line)
}
return buffer.String()
}
func geminiLineToHtml(line string) (res string) {
arr := strings.Fields(line)
token := checkLineType(arr)
switch token {
case headerToken:
level, content := makeOutHeader(arr)
res = fmt.Sprintf("<h%v>%v</h%v>", level, content, level)
case linkToken:
source, content := makeOutLink(arr[1:])
res = fmt.Sprintf(`<a href="%v">%v</a>`, source, content)
case quoteToken:
res = "<blockquote>" + LinesToString(arr[1:], " ") + "</blockquote>"
case preformattedToken:
preState = true
res = fmt.Sprintf(`<pre alt="%v">`, LinesToString(arr[1:], " "))
case "pre/empty":
res = "\n"
case "pre/text":
res = line + "\n"
case "pre/end":
preState = false
res = "</pre>"
case "list/begin":
res = "<ul><li>" + LinesToString(arr[1:], " ") + "</li>"
case listItemToken:
res = "<li>" + LinesToString(arr[1:], " ") + "</li>"
case "list/end":
listState = false
res = "</ul>" + geminiLineToHtml(line)
case "linebreak":
res = "<br>"
default:
res = "<p>" + line + "</p>"
}
return
}
func makeOutLink(arr []string) (source, content string) {
switch len(arr) {
case 0:
return "", ""
case 1:
return arr[0], arr[0]
default:
return arr[0], LinesToString(arr[1:], " ")
}
}
func makeOutHeader(arr []string) (level int, content string) {
level = len(arr[0])
content = LinesToString(arr[1:], " ")
return
}
func checkLineType(arr []string) (res string) {
isEmpty := len(arr) == 0
if preState {
if isEmpty {
res = "pre/empty"
} else if arr[0] == preformattedToken {
res = "pre/end"
} else {
res = "pre/text"
}
} else if listState {
if arr[0] == listItemToken {
res = listItemToken
} else {
res = "list/end"
}
} else if isEmpty {
res = "linebreak"
} else if arr[0][0] == headerToken[0] {
res = headerToken
} else {
return arr[0]
}
return
}
func StringToLines(s string) (lines []string, err error) {
scanner := bufio.NewScanner(strings.NewReader(s))
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
err = scanner.Err()
return
}
func LinesToString(lines []string, separator string) string {
buffer := bytes.Buffer{}
for _, line := range lines {
buffer.WriteString(line + separator)
}
return buffer.String()
}