From cec3718bdd089bcf58575740c5ae4f86b27226d1 Mon Sep 17 00:00:00 2001 From: tjpcc Date: Sat, 14 Jan 2023 19:59:12 -0700 Subject: markdown converter --- gemtext/mdconv/convert.go | 72 +++++++++++++++++++++++++++++ gemtext/mdconv/convert_test.go | 102 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 gemtext/mdconv/convert.go create mode 100644 gemtext/mdconv/convert_test.go (limited to 'gemtext/mdconv') diff --git a/gemtext/mdconv/convert.go b/gemtext/mdconv/convert.go new file mode 100644 index 0000000..0c92f9f --- /dev/null +++ b/gemtext/mdconv/convert.go @@ -0,0 +1,72 @@ +package mdconv + +import ( + "fmt" + "io" + "text/template" + + "tildegit.org/tjp/gus/gemtext" +) + +func Convert(wr io.Writer, doc gemtext.Document, overrides *template.Template) error { + tmpl, err := baseTmpl.Clone() + if err != nil { + return err + } + + if overrides != nil { + for _, override := range overrides.Templates() { + tmpl, err = tmpl.AddParseTree(override.Name(), override.Tree) + if err != nil { + return err + } + } + } + + return tmpl.ExecuteTemplate(wr, "mdconv", doc) +} + +var baseTmpl = template.Must(template.New("mdconv").Parse(fmt.Sprintf((` +{{block "header" .}}{{end -}} +{{range . -}} +{{if .Type | eq %d}}{{block "textline" . -}} + {{. -}} +{{end -}} +{{else if .Type | eq %d}}{{block "linkline" . -}} + => [{{if eq .Label ""}}{{.URL}}{{else}}{{.Label}}{{end}}]({{.URL}}) +{{end -}} +{{else if .Type | eq %d}}{{block "preformattoggleline" . -}} + ` + "```" + ` +{{end -}} +{{else if .Type | eq %d}}{{block "preformattedtextline" . -}} + {{. -}} +{{end -}} +{{else if .Type | eq %d}}{{block "heading1line" . -}} + # {{.Body}} +{{end -}} +{{else if .Type | eq %d}}{{block "heading2line" . -}} + ## {{.Body}} +{{end -}} +{{else if .Type | eq %d}}{{block "heading3line" . -}} + ### {{.Body}} +{{end -}} +{{else if .Type | eq %d}}{{block "listitemline" . -}} + * {{.Body}} +{{end -}} +{{else if .Type | eq %d}}{{block "quoteline" . -}} + > {{.Body}} +{{end -}} +{{end -}} +{{end -}} +{{block "footer" .}}{{end -}} +`)[1:], + gemtext.LineTypeText, + gemtext.LineTypeLink, + gemtext.LineTypePreformatToggle, + gemtext.LineTypePreformattedText, + gemtext.LineTypeHeading1, + gemtext.LineTypeHeading2, + gemtext.LineTypeHeading3, + gemtext.LineTypeListItem, + gemtext.LineTypeQuote, +))) diff --git a/gemtext/mdconv/convert_test.go b/gemtext/mdconv/convert_test.go new file mode 100644 index 0000000..6cde08b --- /dev/null +++ b/gemtext/mdconv/convert_test.go @@ -0,0 +1,102 @@ +package mdconv_test + +import ( + "bytes" + "testing" + "text/template" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "tildegit.org/tjp/gus/gemtext" + "tildegit.org/tjp/gus/gemtext/mdconv" +) + +var gmiDoc = ` +# top-level header line + +## subtitle + +This is some non-blank regular text. + +* an +* unordered +* list + +=> gemini://google.com/ as if +=> https://google.com/ + +> this is a quote +> -tjp + +`[1:] + "```pre-formatted code\ndoc := gemtext.Parse(req.Body)\n```ignored closing alt-text\n" + +func TestConvert(t *testing.T) { + mdDoc := ` +# top-level header line + +## subtitle + +This is some non-blank regular text. + +* an +* unordered +* list + +=> [as if](gemini://google.com/) +=> [https://google.com/](https://google.com/) + +> this is a quote +> -tjp + +`[1:] + "```\ndoc := gemtext.Parse(req.Body)\n```\n" + + doc, err := gemtext.Parse(bytes.NewBufferString(gmiDoc)) + require.Nil(t, err) + + buf := &bytes.Buffer{} + require.Nil(t, mdconv.Convert(buf, doc, nil)) + + assert.Equal(t, mdDoc, buf.String()) +} + +func TestConvertWithOverrides(t *testing.T) { + mdDoc := ` +# h1: top-level header line +text: +## h2: subtitle +text: +text: This is some non-blank regular text. +text: +* li: an +* li: unordered +* li: list +text: +=> link: [as if](gemini://google.com/) +=> link: [https://google.com/](https://google.com/) +text: +> quote: this is a quote +> quote: -tjp +text: +`[1:] + "pftoggle: ```\npf: doc := gemtext.Parse(req.Body)\npftoggle: ```\n" + + overrides := template.Must(template.New("overrides").Parse((` + {{define "textline"}}text: {{.}}{{end}} + {{define "linkline"}}=> link: [{{if eq .Label ""}}{{.URL}}{{else}}{{.Label}}{{end}}]({{.URL}})` + "\n" + `{{end}} + {{define "preformattoggleline"}}pftoggle: ` + "```\n" + `{{end}} + {{define "preformattedtextline"}}pf: {{.}}{{end}} + {{define "heading1line"}}# h1: {{.Body}}` + "\n" + `{{end}} + {{define "heading2line"}}## h2: {{.Body}}` + "\n" + `{{end}} + {{define "heading3line"}}### h3: {{.Body}}` + "\n" + `{{end}} + {{define "listitemline"}}* li: {{.Body}}` + "\n" + `{{end}} + {{define "quoteline"}}> quote: {{.Body}}` + "\n" + `{{end}} + `)[1:])) + + doc, err := gemtext.Parse(bytes.NewBufferString(gmiDoc)) + require.Nil(t, err) + + buf := &bytes.Buffer{} + require.Nil(t, mdconv.Convert(buf, doc, overrides)) + + assert.Equal(t, mdDoc, buf.String()) +} -- cgit v1.2.3