This repository has been archived on 2020-11-14. You can view files and clone it, but cannot push or open issues or pull requests.
go-gemtext/render.go

133 lines
3.2 KiB
Go

package gemtext
import (
"fmt"
"path/filepath"
"strings"
"html"
)
// addPrefix adds the prefix "pref" to a path if it is absolute
// this is to allow protocol-independent absolute links.
func addPrefix(pref string, link string) string {
if filepath.IsAbs(link) {
return filepath.Join(pref, link)
} else {
return link
}
}
// RenderLink takes a GemtextObject and returns a gemini link as a string or an error if the object is not a link.
func RenderLink(obj GemtextObject) (string, error) {
if obj.Type != LINK {
return "", fmt.Errorf("Invalid Link")
} else if obj.Path == "" {
return "", fmt.Errorf("Invalid Link")
}
str := fmt.Sprintf("=> %s %s",obj.Path, obj.Text)
return str,nil
}
// RenderHeading takes a GemtextObject and returns a gemini heading as a string or an error if the object is not a heading.
func RenderHeading(obj GemtextObject) (string, error) {
if obj.Type != HEADING {
return "", fmt.Errorf("Invalid Heading (Not a Heading)")
} else if obj.Level > 3 {
return "", fmt.Errorf("Invalid Heading (Invalid level)")
}
return strings.Repeat("#", obj.Level) + " " + obj.Text, nil
}
// RenderGemtext takes a *GemtextPage and renders it into Gemtext.
func RenderGemtext(p *GemtextPage) (string, error) {
str := ""
for _, o := range *p {
switch {
case o.Type == TEXT:
str += o.Text + "\n"
case o.Type == LINK:
l, err := RenderLink(o)
if err != nil {
return "", err
}
str += l + "\n"
case o.Type == PREFORMATTED_TOGGLE:
str += "```" + o.Text + "\n"
case o.Type == PREFORMATTED_TEXT:
str += o.Text + "\n"
case o.Type == HEADING:
l, err := RenderHeading(o)
if err != nil {
return "", err
}
str += l + "\n"
case o.Type == LIST:
str += "* " + o.Text + "\n"
case o.Type == QUOTE:
str += ">" + o.Text + "\n"
}
}
return str, nil
}
// RenderHTML renders a *GemtextPage p to a string containing html.
func RenderHTML(p *GemtextPage) (string, error) {
escape := html.EscapeString // for brevity
listmode := false
quotemode := false
premode := false
var s string
for _, item := range *p {
if listmode {
if item.Type != LIST {
s += "</ul>"
listmode = false
}
}
if quotemode {
if item.Type != QUOTE {
s += "</blockquote>"
quotemode = false
}}
switch {
case item.Type == TEXT:
s += fmt.Sprintf("<p>%s</p>", escape(item.Text))
case item.Type == LINK:
s += fmt.Sprintf("<a href=\"%s\">%s</a><br />", escape(item.Path), escape(item.Text))
case item.Type == PREFORMATTED_TOGGLE:
if premode {
s += "</pre>"
premode = false
} else {
s += "<pre>"
premode = true
}
case item.Type == PREFORMATTED_TEXT:
s += escape(item.Text) + "\n"
case item.Type == HEADING:
s += fmt.Sprintf("<h%d>%s</h%d>", item.Level, escape(item.Text), item.Level)
case item.Type == LIST:
if !listmode {
s += "<ul>"
listmode = true
}
s += fmt.Sprintf("<li>%s</li>", escape(item.Text))
case item.Type == QUOTE:
if !quotemode {
s += "<blockquote>"
quotemode = true
}
s += escape(item.Text) + "\n"
}
}
if listmode {
s += "</ul>"
}
if quotemode {
s += "</blockquote>"
}
if premode {
s += "</pre>"
}
return s, nil
}