file.go (2248B)
1 package main 2 3 import ( 4 "github.com/gorilla/mux" 5 // "fmt" 6 "html/template" 7 "github.com/go-git/go-git/v5/plumbing" 8 "log" 9 "net/http" 10 "path/filepath" 11 "strings" 12 13 // Chroma 14 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 15 "github.com/alecthomas/chroma/v2/lexers" 16 "github.com/alecthomas/chroma/v2/styles" 17 ) 18 19 type FilePageData struct { 20 Name string 21 Content template.HTML 22 Ref string 23 } 24 25 func getFile(w http.ResponseWriter, r *http.Request) { 26 logger := log.Default() 27 vars := mux.Vars(r) 28 reponame := vars["repository"] 29 30 repo, err := checkRepo(reponame) 31 if err != nil { 32 w.WriteHeader(http.StatusNotFound) 33 return 34 } 35 36 hash, err := repo.ResolveRevision(plumbing.Revision(vars["ref"])) 37 if err != nil { 38 w.WriteHeader(http.StatusNotFound) 39 return 40 } 41 42 commit, err := repo.CommitObject(*hash) 43 if err != nil { 44 w.WriteHeader(http.StatusNotFound) 45 return 46 } 47 48 // Get the path of the entry 49 path := r.RequestURI[len("/repos/") + len(reponame) + len("/file/") + len(vars["ref"]) + 1:len(r.RequestURI)] 50 logger.Printf("Trying to get file: %s (%s)", path, r.RequestURI) 51 entry, err := commit.File(path) 52 if err != nil { 53 w.WriteHeader(http.StatusNotFound) 54 return 55 } 56 57 content, err := entry.Contents() 58 if err != nil { 59 logger.Fatal(err) 60 } 61 62 lexer := lexers.Match(path) 63 if lexer == nil { 64 lexer = lexers.Fallback 65 } 66 67 if err != nil { 68 logger.Fatal(err) 69 } 70 71 var formatter = chromahtml.New( 72 chromahtml.WithLineNumbers(true), 73 chromahtml.WithClasses(true), 74 chromahtml.WithLinkableLineNumbers(true, ""), 75 ) 76 77 if formatter == nil { 78 logger.Fatal("Could not get html formatter") 79 } 80 81 iterator, err := lexer.Tokenise(nil, content) 82 if err != nil { 83 w.WriteHeader(http.StatusInternalServerError) 84 return 85 } 86 87 sbuilder := new(strings.Builder) 88 formatter.Format(sbuilder, styles.Fallback, iterator) 89 90 w.WriteHeader(http.StatusOK) 91 92 tmpl := template.Must(template.ParseFiles( 93 filepath.Join("templates", "file.html"), 94 filepath.Join("templates", "wrap.html"), 95 )) 96 97 _, ishtmx := r.Header["Hx-Request"] 98 99 data := FilePageData { 100 Name: reponame, 101 Content: template.HTML(sbuilder.String()), 102 Ref: commit.Hash.String(), 103 } 104 105 if ishtmx { 106 tmpl.ExecuteTemplate(w, "file_content", data) 107 } else { 108 tmpl.Execute(w, data) 109 } 110 }