From d24c5846c4c202ba083493fc0405a821928cbf0e Mon Sep 17 00:00:00 2001 From: Nihilazo Date: Thu, 12 Nov 2020 21:02:05 +0000 Subject: [PATCH] finish gemtext renderer for now --- render.go | 55 ++++++++++++++++++++++++++++++++++++++++++++------ render_test.go | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 render_test.go diff --git a/render.go b/render.go index 6beeaa4..13c5752 100644 --- a/render.go +++ b/render.go @@ -3,6 +3,7 @@ package gemtext import ( "fmt" "path/filepath" + "strings" ) // addPrefix adds the prefix "pref" to a path if it is absolute @@ -17,11 +18,53 @@ func addPrefix(pref string, link string) string { // RenderLink takes a GemtextObject and returns a gemini link as a string or an error if the object is not a link. func RenderLink(obj GemtextObject) (string, error) { - if obj.Type != LINK { - return "", fmt.Errorf("Not a link!") - } else { - str := fmt.Sprintf("=> %s %s",obj.Path, obj.Text) - return str,nil - } + if obj.Type != LINK { + return "", fmt.Errorf("Invalid Link") + } else if obj.Path == "" { + return "", fmt.Errorf("Invalid Link") + } + str := fmt.Sprintf("=> %s %s",obj.Path, obj.Text) + return str,nil } +// RenderHeading takes a GemtextObject and returns a gemini heading as a string or an error if the object is not a heading. +func RenderHeading(obj GemtextObject) (string, error) { + if obj.Type != HEADING { + return "", fmt.Errorf("Invalid Heading (Not a Heading)") + } else if obj.Level > 3 { + return "", fmt.Errorf("Invalid Heading (Invalid level)") + } + return strings.Repeat("#", obj.Level) + " " + obj.Text, nil +} + +// RenderGemtext takes a GemtextPage and renders it into Gemtext. +func RenderGemtext(p GemtextPage) (string, error) { + str := "" + for _, o := range p { + switch { + case o.Type == TEXT: + str += o.Text + "\n" + case o.Type == LINK: + l, err := RenderLink(o) + if err != nil { + return "", err + } + str += l + "\n" + case o.Type == PREFORMATTED_TOGGLE: + str += "```" + o.Text + "\n" + case o.Type == PREFORMATTED_TEXT: + str += o.Text + "\n" + case o.Type == HEADING: + l, err := RenderHeading(o) + if err != nil { + return "", err + } + str += l + "\n" + case o.Type == LIST: + str += "* " + o.Text + "\n" + case o.Type == QUOTE: + str += ">" + o.Text + "\n" + } + } + return str, nil +} \ No newline at end of file diff --git a/render_test.go b/render_test.go new file mode 100644 index 0000000..1bf3f24 --- /dev/null +++ b/render_test.go @@ -0,0 +1,48 @@ +package gemtext + +import "testing" + +type PrefixCase struct { + Prefix string + Link string + Want string +} + +func TestAddPrefix(t *testing.T) { + cases := []PrefixCase{ + PrefixCase{Prefix: "", Link: "/test/", Want: "/test"}, + PrefixCase{Prefix:"https:itwont.work/", Link: "/test/stuff.gmi", Want: "https:itwont.work/test/stuff.gmi"}, + PrefixCase{Prefix:"https:itwont.work/", Link: "test/stuff.gmi", Want: "test/stuff.gmi"}, + PrefixCase{Prefix:"", Link: "", Want: ""}, + PrefixCase{Prefix:"https:itwont.work/", Link: "", Want: ""}, + } + for _, c := range cases { + got := addPrefix(c.Prefix,c.Link) + if got != c.Want { + t.Errorf("Case %#v, Got %#v", c, got) + } + + } +} + +type LineRenderCase struct { + In GemtextObject + Want string +} + +func TestRenderHeading(t *testing.T) { + cases := []LineRenderCase{ + LineRenderCase{In: GemtextObject{Type: HEADING, Level: 1, Text: "Hello"}, Want:"# Hello"}, // I'm not adding a Literal to these cases. + LineRenderCase{In: GemtextObject{Type: HEADING, Level: 2, Text: ""}, Want:"## "}, + LineRenderCase{In: GemtextObject{Type: HEADING, Level: 2, Text: "Hello"}, Want:"## Hello"}, + LineRenderCase{In: GemtextObject{Type: HEADING, Level: 3, Text: "This contains spaces"}, Want:"### This contains spaces"}, + + + } + for _, c := range cases { + got, _ := RenderHeading(c.In) + if got != c.Want { + t.Errorf("Case %#v, Got %#v", c, got) + } + } +} \ No newline at end of file