From ac770231436f8a17d348a6a0ab934429df3c57d0 Mon Sep 17 00:00:00 2001 From: Feuerfuchs Date: Mon, 18 May 2020 16:12:43 +0200 Subject: WIP: Refactoring --- internal/port/gemini.go | 176 ++++++++++++++++++------------------------------ 1 file changed, 64 insertions(+), 112 deletions(-) (limited to 'internal/port/gemini.go') diff --git a/internal/port/gemini.go b/internal/port/gemini.go index b10da7d..0d8292c 100644 --- a/internal/port/gemini.go +++ b/internal/port/gemini.go @@ -1,7 +1,6 @@ package port import ( - "bufio" "bytes" "fmt" "html/template" @@ -10,7 +9,6 @@ import ( "mime" "net/http" "net/url" - "regexp" "strings" "golang.org/x/net/html/charset" @@ -21,129 +19,83 @@ import ( "github.com/temoto/robotstxt" ) -type SectionType byte - -const ( - RAW_TEXT = SectionType(0) - REFLOW_TEXT = SectionType(1) - LINK = SectionType(2) -) - -type Section struct { - Type SectionType - Text string - URL template.URL -} - -type templateVariables struct { +type GeminiTemplateVariables struct { Title string - URI string + URL string Assets AssetList - Sections []Section + Sections []GeminiSection + Nav []GeminiNavItem } -var ( - TermEscapeSGRPattern = regexp.MustCompile("\\[\\d+(;\\d+)*m") -) +type GeminiNavItem struct { + Label string + URL string +} -func resolveURI(uri string, baseURL *url.URL) (resolvedURI string) { +type GeminiSection struct { + Type libgemini.GeminiDocSectionType + Text string + URL template.URL + Items []string +} + +func resolveURL(uri string, baseURL *url.URL) (resolvedURL string) { if strings.HasPrefix(uri, "//") { - resolvedURI = "/gemini/" + strings.TrimPrefix(uri, "//") + resolvedURL = "/gemini/" + strings.TrimPrefix(uri, "//") } else if strings.HasPrefix(uri, "gemini://") { - resolvedURI = "/gemini/" + strings.TrimPrefix(uri, "gemini://") + resolvedURL = "/gemini/" + strings.TrimPrefix(uri, "gemini://") } else if strings.HasPrefix(uri, "gopher://") { - resolvedURI = "/gopher/" + strings.TrimPrefix(uri, "gopher://") + resolvedURL = "/gopher/" + strings.TrimPrefix(uri, "gopher://") } else { url, err := url.Parse(uri) if err != nil { return "" } - adjustedURI := baseURL.ResolveReference(url) - path := adjustedURI.Path + adjustedURL := baseURL.ResolveReference(url) + path := adjustedURL.Path if !strings.HasPrefix(path, "/") { path = "/" + path } - if adjustedURI.Scheme == "gemini" { - resolvedURI = "/gemini/" + adjustedURI.Host + path - } else if adjustedURI.Scheme == "gopher" { - resolvedURI = "/gopher/" + adjustedURI.Host + path + if adjustedURL.Scheme == "gemini" { + resolvedURL = "/gemini/" + adjustedURL.Host + path + } else if adjustedURL.Scheme == "gopher" { + resolvedURL = "/gopher/" + adjustedURL.Host + path } else { - resolvedURI = adjustedURI.String() + resolvedURL = adjustedURL.String() } } return } -func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (sections []Section) { +func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (sections []GeminiSection) { baseURL, err := url.Parse(fmt.Sprintf( "gemini://%s/%s", hostport, uri, )) if err != nil { - return []Section{} - } - - skipSection := true - - section := Section{ - Type: RAW_TEXT, + return } - scanner := bufio.NewScanner(body) + unpreppedSections := libgemini.ParseGeminiDocument(body) - for scanner.Scan() { - line := strings.Trim(scanner.Text(), "\r\n") - line = TermEscapeSGRPattern.ReplaceAllString(line, "") - - linkMatch := libgemini.LinkPattern.FindStringSubmatch(line) - if len(linkMatch) != 0 && linkMatch[0] != "" { - curType := section.Type - - if !skipSection { - sections = append(sections, section) - } - - label := linkMatch[2] - if label == "" { - label = linkMatch[1] - } - - sections = append(sections, Section{ - Type: LINK, - Text: label, - URL: template.URL(resolveURI(linkMatch[1], baseURL)), + for _, section := range unpreppedSections { + if section.Type != libgemini.LINK { + sections = append(sections, GeminiSection{ + Type: section.Type, + Text: section.Text, + URL: template.URL(section.URL), + Items: section.Items, }) - - skipSection = false - section = Section{ - Type: curType, - } - } else { - reflowModeMatch := libgemini.ReflowModePattern.FindStringSubmatch(line) - if len(reflowModeMatch) != 0 { - newType := RAW_TEXT - if section.Type == RAW_TEXT { - newType = REFLOW_TEXT - } - - if !skipSection { - sections = append(sections, section) - } - - skipSection = false - section = Section{ - Type: newType, - } - } else { - section.Text = section.Text + "\n" + line - } } - } - if !skipSection { - sections = append(sections, section) + sections = append(sections, GeminiSection{ + Type: section.Type, + Text: section.Text, + URL: template.URL(resolveURL(section.URL, baseURL)), + Items: section.Items, + }) } return @@ -176,12 +128,12 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) if err != nil { - if e := tpl.Execute(w, templateVariables{ + if e := tpl.Execute(w, GeminiTemplateVariables{ Title: title, - URI: hostport, + URL: hostport, Assets: assetList, - Sections: []Section{{ - Type: RAW_TEXT, + Sections: []GeminiSection{{ + Type: libgemini.RAW_TEXT, Text: fmt.Sprintf("Error: %s", err), }}, }); e != nil { @@ -205,12 +157,12 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass ) if err != nil { - if e := tpl.Execute(w, templateVariables{ + if e := tpl.Execute(w, GeminiTemplateVariables{ Title: title, - URI: fmt.Sprintf("%s/%s", hostport, uri), + URL: fmt.Sprintf("%s/%s", hostport, uri), Assets: assetList, - Sections: []Section{{ - Type: RAW_TEXT, + Sections: []GeminiSection{{ + Type: libgemini.RAW_TEXT, Text: fmt.Sprintf("Error: %s", err), }}, }); e != nil { @@ -227,12 +179,12 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass uri, )) if err != nil { - if e := tpl.Execute(w, templateVariables{ + if e := tpl.Execute(w, GeminiTemplateVariables{ Title: title, - URI: fmt.Sprintf("%s/%s", hostport, uri), + URL: fmt.Sprintf("%s/%s", hostport, uri), Assets: assetList, - Sections: []Section{{ - Type: RAW_TEXT, + Sections: []GeminiSection{{ + Type: libgemini.RAW_TEXT, Text: fmt.Sprintf("Error: %s", err), }}, }); e != nil { @@ -242,17 +194,17 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass return } - http.Redirect(w, req, resolveURI(res.Header.Meta, baseURL), http.StatusFound) + http.Redirect(w, req, resolveURL(res.Header.Meta, baseURL), http.StatusFound) return } if int(res.Header.Status/10) != 2 { - if err := tpl.Execute(w, templateVariables{ + if err := tpl.Execute(w, GeminiTemplateVariables{ Title: title, - URI: fmt.Sprintf("%s/%s", hostport, uri), + URL: fmt.Sprintf("%s/%s", hostport, uri), Assets: assetList, - Sections: []Section{{ - Type: RAW_TEXT, + Sections: []GeminiSection{{ + Type: libgemini.RAW_TEXT, Text: fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta), }}, }); err != nil { @@ -277,20 +229,20 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass writer.Close() } - var sections []Section + var sections []GeminiSection if strings.HasPrefix(res.Header.Meta, libgemini.MIME_GEMINI) { sections = parseGeminiDocument(buf, uri, hostport) } else { - sections = append(sections, Section{ - Type: RAW_TEXT, + sections = append(sections, GeminiSection{ + Type: libgemini.RAW_TEXT, Text: buf.String(), }) } - if err := tpl.Execute(w, templateVariables{ + if err := tpl.Execute(w, GeminiTemplateVariables{ Title: title, - URI: fmt.Sprintf("%s/%s", hostport, uri), + URL: fmt.Sprintf("%s/%s", hostport, uri), Assets: assetList, Sections: sections, }); err != nil { -- cgit v1.3.1