this repo has no description
1package routes 2 3import ( 4 "bytes" 5 "fmt" 6 "html/template" 7 "io" 8 "log" 9 "net/http" 10 "path/filepath" 11 "strings" 12 13 "github.com/alecthomas/chroma/v2/formatters/html" 14 "github.com/alecthomas/chroma/v2/lexers" 15 "github.com/alecthomas/chroma/v2/styles" 16 "github.com/icyphox/bild/legit/git" 17) 18 19func (h *Handle) Write404(w http.ResponseWriter) { 20 w.WriteHeader(404) 21 if err := h.t.ExecuteTemplate(w, "404", nil); err != nil { 22 log.Printf("404 template: %s", err) 23 } 24} 25 26func (h *Handle) Write500(w http.ResponseWriter) { 27 w.WriteHeader(500) 28 if err := h.t.ExecuteTemplate(w, "500", nil); err != nil { 29 log.Printf("500 template: %s", err) 30 } 31} 32 33func (h *Handle) WriteOOBNotice(w http.ResponseWriter, id, msg string) { 34 html := fmt.Sprintf(`<span id="%s" hx-swap-oob="innerHTML">%s</span>`, id, msg) 35 36 w.Header().Set("Content-Type", "text/html") 37 w.WriteHeader(http.StatusOK) 38 w.Write([]byte(html)) 39} 40 41func (h *Handle) listFiles(files []git.NiceTree, data map[string]any, w http.ResponseWriter) { 42 tpath := filepath.Join(h.c.Dirs.Templates, "*") 43 t := template.Must(template.ParseGlob(tpath)) 44 45 data["files"] = files 46 data["meta"] = h.c.Meta 47 48 if err := t.ExecuteTemplate(w, "tree", data); err != nil { 49 log.Println(err) 50 return 51 } 52} 53 54func countLines(r io.Reader) (int, error) { 55 buf := make([]byte, 32*1024) 56 bufLen := 0 57 count := 0 58 nl := []byte{'\n'} 59 60 for { 61 c, err := r.Read(buf) 62 if c > 0 { 63 bufLen += c 64 } 65 count += bytes.Count(buf[:c], nl) 66 67 switch { 68 case err == io.EOF: 69 /* handle last line not having a newline at the end */ 70 if bufLen >= 1 && buf[(bufLen-1)%(32*1024)] != '\n' { 71 count++ 72 } 73 return count, nil 74 case err != nil: 75 return 0, err 76 } 77 } 78} 79 80func (d *Handle) showFileWithHighlight(name, content string, data map[string]any, w http.ResponseWriter) { 81 tpath := filepath.Join(d.c.Dirs.Templates, "*") 82 t := template.Must(template.ParseGlob(tpath)) 83 84 lexer := lexers.Get(name) 85 if lexer == nil { 86 lexer = lexers.Get(".txt") 87 } 88 89 style := styles.Get(d.c.Meta.SyntaxHighlight) 90 if style == nil { 91 style = styles.Get("monokailight") 92 } 93 94 formatter := html.New( 95 html.WithLineNumbers(true), 96 html.WithLinkableLineNumbers(true, "L"), 97 ) 98 99 iterator, err := lexer.Tokenise(nil, content) 100 if err != nil { 101 d.Write500(w) 102 return 103 } 104 105 var code bytes.Buffer 106 err = formatter.Format(&code, style, iterator) 107 if err != nil { 108 d.Write500(w) 109 return 110 } 111 112 data["content"] = template.HTML(code.String()) 113 data["meta"] = d.c.Meta 114 data["chroma"] = true 115 116 if err := t.ExecuteTemplate(w, "file", data); err != nil { 117 log.Println(err) 118 return 119 } 120} 121 122func (d *Handle) showFile(content string, data map[string]any, w http.ResponseWriter) { 123 tpath := filepath.Join(d.c.Dirs.Templates, "*") 124 t := template.Must(template.ParseGlob(tpath)) 125 126 lc, err := countLines(strings.NewReader(content)) 127 if err != nil { 128 // Non-fatal, we'll just skip showing line numbers in the template. 129 log.Printf("counting lines: %s", err) 130 } 131 132 lines := make([]int, lc) 133 if lc > 0 { 134 for i := range lines { 135 lines[i] = i + 1 136 } 137 } 138 139 data["linecount"] = lines 140 data["content"] = content 141 data["meta"] = d.c.Meta 142 data["chroma"] = false 143 144 if err := t.ExecuteTemplate(w, "file", data); err != nil { 145 log.Println(err) 146 return 147 } 148} 149 150func (d *Handle) showRaw(content string, w http.ResponseWriter) { 151 w.WriteHeader(http.StatusOK) 152 w.Header().Set("Content-Type", "text/plain") 153 w.Write([]byte(content)) 154 return 155}