This repository has been archived on 2023-05-01. You can view files and clone it, but cannot push or open issues or pull requests.
gus/gemini/gemtext/mdconv/convert.go

79 lines
2.5 KiB
Go

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 }}
`))