diff options
Diffstat (limited to 'gemtext/internal/templates.go')
-rw-r--r-- | gemtext/internal/templates.go | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/gemtext/internal/templates.go b/gemtext/internal/templates.go new file mode 100644 index 0000000..dea528a --- /dev/null +++ b/gemtext/internal/templates.go @@ -0,0 +1,150 @@ +package internal + +import ( + htemplate "html/template" + "net/url" + "text/template" + + "tildegit.org/tjp/gus/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()) +} |