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