133 lines
3.2 KiB
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
|
|
} |