summaryrefslogtreecommitdiff
path: root/gemini/gemtext/mdconv/convert.go
diff options
context:
space:
mode:
Diffstat (limited to 'gemini/gemtext/mdconv/convert.go')
-rw-r--r--gemini/gemtext/mdconv/convert.go78
1 files changed, 78 insertions, 0 deletions
diff --git a/gemini/gemtext/mdconv/convert.go b/gemini/gemtext/mdconv/convert.go
new file mode 100644
index 0000000..c2f434d
--- /dev/null
+++ b/gemini/gemtext/mdconv/convert.go
@@ -0,0 +1,78 @@
+package mdconv
+
+import (
+ "io"
+ "text/template"
+
+ "tildegit.org/tjp/gus/gemini/gemtext"
+ "tildegit.org/tjp/gus/gemini/gemtext/internal"
+)
+
+// Convert writes markdown to a writer from the provided gemtext document.
+//
+// Templates can be provided to override the output for different line types.
+// The templates supported are:
+// - "header" is called before any lines and is passed the full Document.
+// - "footer" is called after the lines and is passed the full Document.
+// - "textline" is called once per line of text and is passed a gemtext.TextLine.
+// - "linkline" is called once per link line and is passed a gemtext.LinkLine.
+// - "preformattedtextlines" is called once for a block of preformatted text and is
+// passed a slice of gemtext.PreformattedTextLines.
+// - "heading1line" is called once per h1 line and is passed a gemtext.Heading1Line.
+// - "heading2line" is called once per h2 line and is passed a gemtext.Heading2Line.
+// - "heading3line" is called once per h3 line and is passed a gemtext.Heading3Line.
+// - "listitemlines" is called once for a block of contiguous list item lines and
+// is passed a slice of gemtext.ListItemLines.
+// - "quoteline" is passed once per blockquote line and is passed a gemtext.QuoteLine.
+//
+// There exist default implementations of each of these templates, so the "overrides"
+// argument can be nil.
+func Convert(wr io.Writer, doc gemtext.Document, overrides *template.Template) error {
+ if err := internal.ValidateLinks(doc); err != nil {
+ return err
+ }
+
+ tmpl, err := baseTmpl.Clone()
+ if err != nil {
+ return err
+ }
+
+ tmpl, err = internal.AddAllTemplates(tmpl, overrides)
+ if err != nil {
+ return err
+ }
+
+ for _, item := range internal.RenderItems(doc) {
+ if err := tmpl.ExecuteTemplate(wr, item.Template, item.Object); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+var baseTmpl = template.Must(template.New("mdconv").Parse(`
+{{ define "header" }}{{ end }}
+{{ define "textline" }}{{ if ne .String "\n" }}
+{{ . }}{{ end }}{{ end }}
+{{ define "linkline" }}
+=> [{{ if eq .Label "" }}{{ .URL }}{{ else }}{{ .Label }}{{ end }}]({{ .URL }})
+{{ end }}
+{{ define "preformattedtextlines" }}` + "\n```\n" + `{{ range . }}{{ . }}{{ end }}` + "```\n" + `{{ end }}
+{{ define "heading1line" }}
+# {{ .Body }}
+{{ end }}
+{{ define "heading2line" }}
+## {{ .Body }}
+{{ end }}
+{{ define "heading3line" }}
+### {{ .Body }}
+{{ end }}
+{{ define "listitemlines" }}
+{{ range . }}* {{ .Body }}
+{{ end }}{{ end }}
+{{ define "quoteline" }}
+> {{ .Body }}
+{{ end }}
+{{ define "footer" }}{{ end }}
+`))