From 4f1178fc2a3e5865c2fb1c16c83fc1abb15484f9 Mon Sep 17 00:00:00 2001 From: Jordan Date: Sat, 1 Jan 2022 19:43:19 -0700 Subject: crane, http, util: housekeeping, performance improvements, styling --- crane.go | 13 --- http.go | 98 ++++++++-------- templates/admin-edit.html | 105 +++++++++++------ templates/admin.html | 74 ++++++------ templates/index.html | 23 ++-- templates/layout.html | 280 ++++++---------------------------------------- templates/list.html | 65 ++++++++--- util.go | 84 +++++++------- 8 files changed, 303 insertions(+), 439 deletions(-) diff --git a/crane.go b/crane.go index d930bf7..99c3a83 100644 --- a/crane.go +++ b/crane.go @@ -36,7 +36,6 @@ var ( user string pass string buildPrefix string - templateDir string ) type Contributor struct { @@ -639,18 +638,6 @@ func main() { panic(errors.New("Host flag could not be parsed; is it an IP address?")) } - // prefer system-installed template assets over project-local paths - if _, err := os.Stat(filepath.Join(buildPrefix, - "/share/crane/templates")); err != nil { - dir, err := filepath.Abs(filepath.Dir(os.Args[0])) - if err != nil { - log.Fatal(err) - } - templateDir = filepath.Join(dir, "templates") - } else { - templateDir = filepath.Join(buildPrefix, "/share/crane/templates") - } - http.HandleFunc("/", papers.IndexHandler) http.HandleFunc("/admin/", papers.AdminHandler) http.HandleFunc("/admin/edit/", papers.EditHandler) diff --git a/http.go b/http.go index ad42c2b..26cc788 100644 --- a/http.go +++ b/http.go @@ -2,50 +2,74 @@ package main import ( "fmt" - "net/http" "html/template" + "log" + "net/http" "os" "path/filepath" "strings" ) +var templateDir = getTemplateDir() + +var indexTemp = template.Must(template.ParseFiles( + filepath.Join(templateDir, "layout.html"), + filepath.Join(templateDir, "index.html"), + filepath.Join(templateDir, "list.html"), +)) +var adminTemp = template.Must(template.ParseFiles( + filepath.Join(templateDir, "admin.html"), + filepath.Join(templateDir, "layout.html"), + filepath.Join(templateDir, "list.html"), +)) +var editTemp = template.Must(template.ParseFiles( + filepath.Join(templateDir, "admin-edit.html"), + filepath.Join(templateDir, "layout.html"), + filepath.Join(templateDir, "list.html"), +)) + +func cat(cat string) string { + + return strings.Replace(cat, "-", "‑", -1) +} + +// getTemplateDir returns the absolute path of the templates directory, +// preferring system-installed assets over the project-local path +func getTemplateDir() string { + + if _, err := os.Stat(filepath.Join(buildPrefix, + "/share/crane/templates")); err != nil { + dir, err := filepath.Abs(filepath.Dir(os.Args[0])) + if err != nil { + log.Fatal(err) + } + return filepath.Join(dir, "templates") + } else { + return filepath.Join(buildPrefix, "/share/crane/templates") + } +} + // IndexHandler renders the index of papers stored in papers.Path func (papers *Papers) IndexHandler(w http.ResponseWriter, r *http.Request) { + // catch-all for paths unhandled by direct http.HandleFunc calls if r.URL.Path != "/" { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } - t, _ := template.ParseFiles(filepath.Join(templateDir, "layout.html"), - filepath.Join(templateDir, "index.html"), - filepath.Join(templateDir, "list.html"), - ) - papers.RLock() - res := Resp{ - Papers: *papers, - } - papers.RUnlock() - - t.Execute(w, &res) + res := Resp{Papers: *papers} + indexTemp.Execute(w, &res) } // AdminHandler renders the index of papers stored in papers.Path with // additional forms to modify the collection (add, delete, rename...) func (papers *Papers) AdminHandler(w http.ResponseWriter, r *http.Request) { - t, _ := template.ParseFiles(filepath.Join(templateDir, "admin.html"), - filepath.Join(templateDir, "layout.html"), - filepath.Join(templateDir, "list.html"), - ) - papers.RLock() - res := Resp{ - Papers: *papers, - } - papers.RUnlock() + res := Resp{Papers: *papers} if user != "" && pass != "" { username, password, ok := r.BasicAuth() if ok && user == username && pass == password { - t.Execute(w, &res) + adminTemp.Execute(w, &res) } else { w.Header().Add("WWW-Authenticate", `Basic realm="Please authenticate"`) @@ -53,23 +77,15 @@ func (papers *Papers) AdminHandler(w http.ResponseWriter, r *http.Request) { http.StatusUnauthorized) } } else { - t.Execute(w, &res) + adminTemp.Execute(w, &res) } } // EditHandler renders the index of papers stored in papers.Path, prefixing // a checkbox to each unique paper and category for modification func (papers *Papers) EditHandler(w http.ResponseWriter, r *http.Request) { - t, _ := template.ParseFiles(filepath.Join(templateDir, "admin-edit.html"), - filepath.Join(templateDir, "layout.html"), - filepath.Join(templateDir, "list.html"), - ) - papers.RLock() - res := Resp{ - Papers: *papers, - } - papers.RUnlock() + res := Resp{Papers: *papers} if user != "" && pass != "" { username, password, ok := r.BasicAuth() if !ok || user != username || pass != password { @@ -82,10 +98,9 @@ func (papers *Papers) EditHandler(w http.ResponseWriter, r *http.Request) { } if err := r.ParseForm(); err != nil { res.Status = err.Error() - t.Execute(w, &res) + editTemp.Execute(w, &res) return } - if action := r.FormValue("action"); action == "delete" { for _, paper := range r.Form["paper"] { if res.Status != "" { @@ -135,15 +150,12 @@ func (papers *Papers) EditHandler(w http.ResponseWriter, r *http.Request) { } } } - t.Execute(w, &res) + editTemp.Execute(w, &res) } // AddHandler provides support for new paper processing and category addition func (papers *Papers) AddHandler(w http.ResponseWriter, r *http.Request) { - t, _ := template.ParseFiles(filepath.Join(templateDir, "admin.html"), - filepath.Join(templateDir, "layout.html"), - filepath.Join(templateDir, "list.html"), - ) + if user != "" && pass != "" { username, password, ok := r.BasicAuth() if !ok || user != username || pass != password { @@ -161,7 +173,6 @@ func (papers *Papers) AddHandler(w http.ResponseWriter, r *http.Request) { // sanitize input; we use the category to build the path used to save // papers nc = strings.Trim(strings.Replace(nc, "..", "", -1), "/.") - res := Resp{} // paper download, both required fields populated @@ -204,15 +215,13 @@ func (papers *Papers) AddHandler(w http.ResponseWriter, r *http.Request) { res.Status = fmt.Sprintf("category %q added successfully", nc) } } - papers.RLock() res.Papers = *papers - papers.RUnlock() - - t.Execute(w, &res) + adminTemp.Execute(w, &res) } // DownloadHandler serves saved papers up for download func (papers *Papers) DownloadHandler(w http.ResponseWriter, r *http.Request) { + paper := strings.TrimPrefix(r.URL.Path, "/download/") category := filepath.Dir(paper) @@ -241,4 +250,3 @@ func (papers *Papers) DownloadHandler(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, papers.List[category][paper].PaperPath) } } - diff --git a/templates/admin-edit.html b/templates/admin-edit.html index 5bd4fa1..d8805f9 100644 --- a/templates/admin-edit.html +++ b/templates/admin-edit.html @@ -1,32 +1,40 @@ {{ template "layout.html" . }} {{ define "content" }} -

{{ .Status }}

- + + + + {{ $categoryCount := len .Papers.List }} {{ if gt $categoryCount 0 }} - {{ end }} -
- {{ range $category, $paper := .Papers.List }}[{{ $category }}] {{ end }} +
+
+ {{ range $category, $paper := .Papers.List }} + [{{ $category }}] + {{ end }} +
- - - - -
Back
+

Back

{{ if gt $categoryCount 0 }}
@@ -41,43 +49,76 @@ {{ end }} - +
-
+
{{ range $category, $papers := .Papers.List }} {{ $paperCount := len $papers }} -
- - -
+ + {{ range $path, $paper := $papers }} -
    -
  • +
    {{ if $paper.Meta.Title }} - {{ $paper.Meta.Title }}
    + + + {{ $paper.Meta.Title }} + +
    {{ else }} -
    + + + + +
    {{ end }} {{ $contCount := len $paper.Meta.Contributors }}{{ if ge $contCount 1 }} - {{ range $index, $contributor := $paper.Meta.Contributors }}{{if $index}}, {{end}}{{ $contributor.FirstName }} {{ $contributor.LastName }}{{end}}
    + + {{- range $index, $contributor := $paper.Meta.Contributors -}} + {{- if $index }}, {{ end }} + {{- $contributor.FirstName }} {{ $contributor.LastName -}} + {{- end -}} + +
    {{ end }} {{ $hasVal := false }} - {{ if $paper.Meta.PubYear }}{{ $hasVal = true }}{{ $paper.Meta.PubYear }}{{ end }} - - {{ if $paper.Meta.DOI }}{{ if $hasVal }}- {{end}}{{ $paper.Meta.DOI }} + {{ if $paper.Meta.PubYear }}{{ $hasVal = true }} + {{ $paper.Meta.PubYear }} + {{ end }} - {{ else if $paper.Meta.ArxivID }}{{ if $hasVal }}- {{ end }}{{ $paper.Meta.ArxivID }} - {{ else if $paper.Meta.Resource }}{{ if $hasVal }}- {{ end }}{{ $paper.Meta.Resource }}{{ end }} + {{ if $paper.Meta.DOI }}{{ if $hasVal }}- {{end}} + + {{ $paper.Meta.DOI }} + + {{ else if $paper.Meta.ArxivID }} + {{ if $hasVal }}- {{ end }} + + {{ $paper.Meta.ArxivID }} + + {{ else if $paper.Meta.Resource }} + {{ if $hasVal }}- {{ end }} + + {{ $paper.Meta.Resource }} + + {{ end }} - {{ if $paper.Meta.Journal }}{{ if $hasVal }}- {{ end }}{{ $paper.Meta.Journal }}{{ end }} + {{ if $paper.Meta.Journal }} + {{ if $hasVal }}- {{ end }} + {{ $paper.Meta.Journal }} + + {{ end }} -
  • -
+
{{ end }} -
{{ end }} +
{{ end }}
{{ end }} diff --git a/templates/admin.html b/templates/admin.html index 8573e23..fb3a3d2 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -1,51 +1,55 @@ {{ template "layout.html" . }} {{ define "content" }} -{{ if .LastPaperDL }} -

{{ .Status }} (download)

-{{ else }} -

{{ .Status }}

-{{ end }} - + + + + - + {{ $categoryCount := len .Papers.List }} {{ if gt $categoryCount 0 }} - + {{ end }}
+ {{ if .LastPaperDL }} + {{ .Status }} (download) + {{ else }} + {{ .Status }} + {{ end }} +
-
- - +
+ + + -
-
- - - -
-
+
+ + + +
+
{{ if gt $categoryCount 0 }} -
- {{ range $category, $paper := .Papers.List }}[{{ $category }}] {{ end }} +
+
+ {{ range $category, $paper := .Papers.List }} + [{{ $category }}] + {{ end }} +
- - - - -
Edit
+

Edit

{{ block "list" . }}{{ end }}
diff --git a/templates/index.html b/templates/index.html index d435a38..861410d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,21 +1,22 @@ {{ template "layout.html" . }} {{ define "content" }} - - + +
{{ $categoryCount := len .Papers.List }} {{ if gt $categoryCount 0 }} -
- {{ range $category, $paper := .Papers.List }}[{{ $category }}] {{ end }} +
+
+ {{ range $category, $paper := .Papers.List }} + [{{ $category }}] + {{ end }} +
- - - - -
Manage
-
+

Manage

{{ block "list" . }}{{ end }}
{{ else }} -

nothing here yet, create a category to start downloading papers

+

nothing here yet, +create a category +to start downloading papers

{{ end }} {{ end }} diff --git a/templates/layout.html b/templates/layout.html index b9449b6..9f6109b 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -2,255 +2,49 @@ - + Crane -
-
- - - - +
+

+

Crane is a research literature download and categorization +service. The source code can be downloaded +here.

{{ block "content" . }}{{ end }} -
-
+crane diff --git a/templates/list.html b/templates/list.html index 52e7bb9..132bb6d 100644 --- a/templates/list.html +++ b/templates/list.html @@ -1,37 +1,66 @@ {{ define "list" }} -
+
{{ range $category, $papers := .Papers.List }} {{ $paperCount := len $papers }} {{ if ge $paperCount 1 }} -
- {{ $category }} -
+

+ +

{{ range $path, $paper := $papers }} -
    -
  • +
    {{ if $paper.Meta.Title }} - {{ $paper.Meta.Title }}
    + + {{ $paper.Meta.Title }} + +
    {{ else }} - {{ $paper.PaperName }}
    + + {{ $paper.PaperName }} + +
    {{ end }} - {{ $contCount := len $paper.Meta.Contributors }}{{ if ge $contCount 1 }} - {{ range $index, $contributor := $paper.Meta.Contributors }}{{if $index}}, {{end}}{{ $contributor.FirstName }} {{ $contributor.LastName }}{{end}}
    + {{ $contCount := len $paper.Meta.Contributors }} + {{ if ge $contCount 1 }} + + {{- range $index, $contributor := $paper.Meta.Contributors -}} + {{- if $index }}, {{ end -}} + {{- $contributor.FirstName }} {{ $contributor.LastName -}} + {{- end -}} + +
    {{ end }} {{ $hasVal := false }} - {{ if $paper.Meta.PubYear }}{{ $hasVal = true }}{{ $paper.Meta.PubYear }}{{ end }} + {{ if $paper.Meta.PubYear }} + {{ $hasVal = true }} + {{ $paper.Meta.PubYear }} + {{ end }} - {{ if $paper.Meta.DOI }}{{ if $hasVal }}- {{end}}{{ $paper.Meta.DOI }} + {{ if $paper.Meta.DOI }} + {{ if $hasVal }}- {{end}} + + {{ $paper.Meta.DOI }} + - {{ else if $paper.Meta.ArxivID }}{{ if $hasVal }}- {{ end }}{{ $paper.Meta.ArxivID }} - {{ else if $paper.Meta.Resource }}{{ if $hasVal }}- {{ end }}{{ $paper.Meta.Resource }}{{ end }} + {{ else if $paper.Meta.ArxivID }} + {{ if $hasVal }}- {{ end }} + + {{ $paper.Meta.ArxivID }} + + {{ else if $paper.Meta.Resource }} + {{ if $hasVal }}- {{ end }} + + {{ $paper.Meta.Resource }} + + {{ end }} - {{ if $paper.Meta.Journal }}{{ if $hasVal }}- {{ end }}{{ $paper.Meta.Journal }}{{ end }} -
  • -
+ {{ if $paper.Meta.Journal }} + {{ if $hasVal }}- {{ end }} + {{ $paper.Meta.Journal }} + {{ end }} +
{{ end }} -
{{ end }} {{ end }}
diff --git a/util.go b/util.go index cc2af29..ae9ed98 100644 --- a/util.go +++ b/util.go @@ -99,51 +99,51 @@ func getMetaFromCitation(resp *http.Response) (*Meta, error) { } } switch name { - case "citation_title": - meta.Title = cont - case "citation_author": - var c Contributor - // Doe, Jain - if strings.Contains(cont, ",") { - v := strings.Split(cont, ", ") - c.FirstName = strings.Join(v[1:], " ") - c.LastName = v[0] + case "citation_title": + meta.Title = cont + case "citation_author": + var c Contributor + // Doe, Jain + if strings.Contains(cont, ",") { + v := strings.Split(cont, ", ") + c.FirstName = strings.Join(v[1:], " ") + c.LastName = v[0] // Jain Doe - } else { - v := strings.Split(cont, " ") - c.FirstName = strings.Join(v[:len(v)-1], " ") - c.LastName = strings.Join(v[len(v)-1:], " ") - } - c.Role = "author" - if len(meta.Contributors) > 0 { - c.Sequence = "additional" - } else { - c.Sequence = "first" - } - meta.Contributors = append(meta.Contributors, c) - case "citation_date", "citation_publication_date": - var formats = []string{"2006-01-02", "2006/01/02", "2006"} - for _, format := range formats { - t, err := time.Parse(format, cont) - if err == nil { - meta.PubMonth = t.Month().String() - meta.PubYear = strconv.Itoa(t.Year()) - break - } + } else { + v := strings.Split(cont, " ") + c.FirstName = strings.Join(v[:len(v)-1], " ") + c.LastName = strings.Join(v[len(v)-1:], " ") + } + c.Role = "author" + if len(meta.Contributors) > 0 { + c.Sequence = "additional" + } else { + c.Sequence = "first" + } + meta.Contributors = append(meta.Contributors, c) + case "citation_date", "citation_publication_date": + var formats = []string{"2006-01-02", "2006/01/02", "2006"} + for _, format := range formats { + t, err := time.Parse(format, cont) + if err == nil { + meta.PubMonth = t.Month().String() + meta.PubYear = strconv.Itoa(t.Year()) + break } - case "citation_journal_title", "og:site_name", "DC.Publisher": - meta.Journal = cont - case "citation_firstpage": - meta.FirstPage = cont - case "citation_lastpage": - meta.LastPage = cont - case "citation_doi": - meta.DOI = cont - case "citation_arxiv_id": - meta.ArxivID = cont - case "citation_pdf_url": - meta.Resource = cont } + case "citation_journal_title", "og:site_name", "DC.Publisher": + meta.Journal = cont + case "citation_firstpage": + meta.FirstPage = cont + case "citation_lastpage": + meta.LastPage = cont + case "citation_doi": + meta.DOI = cont + case "citation_arxiv_id": + meta.ArxivID = cont + case "citation_pdf_url": + meta.Resource = cont + } } for c := n.FirstChild; c != nil; c = c.NextSibling { f(c) -- cgit v1.2.3-54-g00ecf