package internal
import (
htemplate "html/template"
"net/url"
"text/template"
"tildegit.org/tjp/gus/gemini/gemtext"
)
var Renderers = map[gemtext.LineType]string{
gemtext.LineTypeText: "textline",
gemtext.LineTypeLink: "linkline",
gemtext.LineTypeHeading1: "heading1line",
gemtext.LineTypeHeading2: "heading2line",
gemtext.LineTypeHeading3: "heading3line",
gemtext.LineTypeQuote: "quoteline",
}
func AddAllTemplates(base *template.Template, additions *template.Template) (*template.Template, error) {
if additions == nil {
return base, nil
}
tmpl := base
var err error
for _, addition := range additions.Templates() {
tmpl, err = tmpl.AddParseTree(addition.Name(), addition.Tree)
if err != nil {
return nil, err
}
}
return tmpl, nil
}
func AddHTMLTemplates(base *htemplate.Template, additions *htemplate.Template) (*htemplate.Template, error) {
if additions == nil {
return base, nil
}
tmpl := base
var err error
for _, addition := range additions.Templates() {
tmpl, err = tmpl.AddParseTree(addition.Name(), addition.Tree)
if err != nil {
return nil, err
}
}
return tmpl, nil
}
func ValidateLinks(doc gemtext.Document) error {
for _, line := range doc {
if linkLine, ok := line.(gemtext.LinkLine); ok {
_, err := url.Parse(linkLine.URL())
if err != nil {
return err
}
}
}
return nil
}
type RenderItem struct {
Template string
Object any
}
func RenderItems(doc gemtext.Document) []RenderItem {
out := make([]RenderItem, 0, len(doc))
out = append(out, RenderItem{
Template: "header",
Object: doc,
})
inUL := false
ulStart := 0
inPF := false
pfStart := 0
for i, line := range doc {
switch line.Type() {
case gemtext.LineTypeListItem:
if !inUL {
inUL = true
ulStart = i
}
case gemtext.LineTypePreformatToggle:
if inUL {
inUL = false
out = append(out, RenderItem{
Template: "listitemlines",
Object: doc[ulStart:i],
})
}
if !inPF {
inPF = true
pfStart = i
} else {
inPF = false
out = append(out, RenderItem{
Template: "preformattedtextlines",
Object: doc[pfStart+1 : i],
})
}
case gemtext.LineTypePreformattedText:
default:
if inUL {
inUL = false
out = append(out, RenderItem{
Template: "listitemlines",
Object: doc[ulStart:i],
})
}
if linkLine, ok := line.(gemtext.LinkLine); ok {
line = validatedLinkLine{linkLine}
}
out = append(out, RenderItem{
Template: Renderers[line.Type()],
Object: line,
})
}
}
if inUL {
out = append(out, RenderItem{
Template: "listitemlines",
Object: doc[ulStart:],
})
}
out = append(out, RenderItem{
Template: "footer",
Object: doc,
})
return out
}
type validatedLinkLine struct {
gemtext.LinkLine
}
func (vll validatedLinkLine) ValidatedURL() htemplate.URL {
return htemplate.URL(vll.URL())
}