From fdd98a148782a322dd590d33989f0f9dc83c0350 Mon Sep 17 00:00:00 2001 From: makeworld Date: Sat, 20 Jun 2020 00:09:01 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Move=20render=20code=20around?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- display/display.go | 12 ------ renderer/page.go | 95 ++++++++++++++++++++++++++++++++++++++++++++ renderer/renderer.go | 89 ----------------------------------------- 3 files changed, 95 insertions(+), 101 deletions(-) create mode 100644 renderer/page.go diff --git a/display/display.go b/display/display.go index c8b0742..135b808 100644 --- a/display/display.go +++ b/display/display.go @@ -399,18 +399,6 @@ func Reload() { // URL loads and handles the provided URL for the current tab. // It should be an absolute URL. func URL(u string) { - // Old relative URL handling stuff: - // parsed, err := url.Parse(u) - // if err != nil { - // Error("Bad URL", err.Error()) - // return - // } - // if tabHasContent() && parsed.Host == "" { - // // Relative link - // followLink(tabMap[curTab].Url, u) - // return - // } - go func() { final, displayed := handleURL(u) if displayed { diff --git a/renderer/page.go b/renderer/page.go new file mode 100644 index 0000000..4f88a05 --- /dev/null +++ b/renderer/page.go @@ -0,0 +1,95 @@ +package renderer + +import ( + "errors" + "io/ioutil" + "mime" + "strings" + + "github.com/makeworld-the-better-one/amfora/structs" + "github.com/makeworld-the-better-one/go-gemini" + "golang.org/x/text/encoding/ianaindex" +) + +// isUTF8 returns true for charsets that are compatible with UTF-8 and don't need to be decoded. +func isUTF8(charset string) bool { + utfCharsets := []string{"", "utf-8", "us-ascii"} + for i := range utfCharsets { + if strings.ToLower(charset) == utfCharsets[i] { + return true + } + } + return false +} + +// CanDisplay returns true if the response is supported by Amfora +// for displaying on the screen. +// It also doubles as a function to detect whether something can be stored in a Page struct. +func CanDisplay(res *gemini.Response) bool { + if gemini.SimplifyStatus(res.Status) != 20 { + // No content + return false + } + mediatype, params, err := mime.ParseMediaType(res.Meta) + if err != nil { + return false + } + if mediatype != "text/gemini" && mediatype != "text/plain" { + // Amfora doesn't support other filetypes + return false + } + if isUTF8(params["charset"]) { + return true + } + enc, err := ianaindex.MIME.Encoding(params["charset"]) // Lowercasing is done inside + // Encoding sometimes returns nil, see #3 on this repo and golang/go#19421 + return err == nil && enc != nil +} + +func MakePage(url string, res *gemini.Response) (*structs.Page, error) { + if !CanDisplay(res) { + return nil, errors.New("not valid content for a Page") + } + + rawText, err := ioutil.ReadAll(res.Body) // TODO: Don't use all memory on large pages + if err != nil { + return nil, err + } + res.Body.Close() + + mediatype, params, _ := mime.ParseMediaType(res.Meta) + + // Convert content first + var utfText string + if isUTF8(params["charset"]) { + utfText = string(rawText) + } else { + encoding, err := ianaindex.MIME.Encoding(params["charset"]) + if encoding == nil || err != nil { + // Some encoding doesn't exist and wasn't caught in CanDisplay() + return nil, errors.New("unsupported encoding") + } + utfText, err = encoding.NewDecoder().String(string(rawText)) + if err != nil { + return nil, err + } + } + + if mediatype == "text/plain" { + return &structs.Page{ + Url: url, + Content: utfText, + Links: []string{}, // Plaintext has no links + }, nil + } + if mediatype == "text/gemini" { + rendered, links := RenderGemini(utfText) + return &structs.Page{ + Url: url, + Content: rendered, + Links: links, + }, nil + } + + return nil, errors.New("displayable mediatype is not handled in the code, implementation error") +} diff --git a/renderer/renderer.go b/renderer/renderer.go index 4c94488..d5227f0 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -5,56 +5,15 @@ package renderer import ( - "errors" - "io/ioutil" - "mime" urlPkg "net/url" "strconv" "strings" "github.com/makeworld-the-better-one/amfora/config" - "github.com/makeworld-the-better-one/amfora/structs" - "github.com/makeworld-the-better-one/go-gemini" "github.com/spf13/viper" "gitlab.com/tslocum/cview" - "golang.org/x/text/encoding/ianaindex" ) -// Charsets that are compatible with UTF-8 and don't need to be decoded. -func isUTF8(charset string) bool { - utfCharsets := []string{"", "utf-8", "us-ascii"} - for i := range utfCharsets { - if strings.ToLower(charset) == utfCharsets[i] { - return true - } - } - return false -} - -// CanDisplay returns true if the response is supported by Amfora -// for displaying on the screen. -// It also doubles as a function to detect whether something can be stored in a Page struct. -func CanDisplay(res *gemini.Response) bool { - if gemini.SimplifyStatus(res.Status) != 20 { - // No content - return false - } - mediatype, params, err := mime.ParseMediaType(res.Meta) - if err != nil { - return false - } - if mediatype != "text/gemini" && mediatype != "text/plain" { - // Amfora doesn't support other filetypes - return false - } - if isUTF8(params["charset"]) { - return true - } - enc, err := ianaindex.MIME.Encoding(params["charset"]) // Lowercasing is done inside - // Encoding sometimes returns nil, see #3 on this repo and golang/go#19421 - return err == nil && enc != nil -} - // convertRegularGemini converts non-preformatted blocks of text/gemini // into a cview-compatible format. // It also returns a slice of link URLs. @@ -214,51 +173,3 @@ func RenderGemini(s string) (string, []string) { return rendered, links } - -func MakePage(url string, res *gemini.Response) (*structs.Page, error) { - if !CanDisplay(res) { - return nil, errors.New("not valid content for a Page") - } - - rawText, err := ioutil.ReadAll(res.Body) // TODO: Don't use all memory on large pages - if err != nil { - return nil, err - } - res.Body.Close() - - mediatype, params, _ := mime.ParseMediaType(res.Meta) - - // Convert content first - var utfText string - if isUTF8(params["charset"]) { - utfText = string(rawText) - } else { - encoding, err := ianaindex.MIME.Encoding(params["charset"]) - if encoding == nil || err != nil { - // Some encoding doesn't exist and wasn't caught in CanDisplay() - return nil, errors.New("unsupported encoding") - } - utfText, err = encoding.NewDecoder().String(string(rawText)) - if err != nil { - return nil, err - } - } - - if mediatype == "text/plain" { - return &structs.Page{ - Url: url, - Content: utfText, - Links: []string{}, // Plaintext has no links - }, nil - } - if mediatype == "text/gemini" { - rendered, links := RenderGemini(utfText) - return &structs.Page{ - Url: url, - Content: rendered, - Links: links, - }, nil - } - - return nil, errors.New("displayable mediatype is not handled in the code, implementation error") -}