summaryrefslogtreecommitdiff
path: root/gemini/gemtext/internal/templates.go
diff options
context:
space:
mode:
authortjpcc <tjp@ctrl-c.club>2023-01-17 16:41:04 -0700
committertjpcc <tjp@ctrl-c.club>2023-01-17 16:41:04 -0700
commit6586db782ea6dcb5f2eb191a690ec7e7df51161f (patch)
tree36158a53a6d8aad9f5a873c6c43d598ce5647b97 /gemini/gemtext/internal/templates.go
parent2ef530daa47b301a40c1ee93cd43b8f36fc68c0b (diff)
Updates
* update README * move "gemtext" to within "gemini"
Diffstat (limited to 'gemini/gemtext/internal/templates.go')
-rw-r--r--gemini/gemtext/internal/templates.go150
1 files changed, 150 insertions, 0 deletions
diff --git a/gemini/gemtext/internal/templates.go b/gemini/gemtext/internal/templates.go
new file mode 100644
index 0000000..08bc66c
--- /dev/null
+++ b/gemini/gemtext/internal/templates.go
@@ -0,0 +1,150 @@
+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())
+}