package routes import ( "bytes" "fmt" "io" "log" "path/filepath" "strings" "alin.ovh/elgit/git" "alin.ovh/elgit/templates" "github.com/microcosm-cc/bluemonday" "github.com/russross/blackfriday/v2" "github.com/savsgio/atreugo/v11" ) func (d *deps) WriteError(rc *atreugo.RequestCtx, err error, i int) error { rc.SetStatusCode(i) data := templates.PageData{ Meta: d.c.Meta, Error: &templates.Error{ Code: i, Message: err.Error(), }, } if err := templates.ErrorPage(data).Render(rc); err != nil { log.Printf("error template: %s", err) return err } return nil } func (d *deps) listFiles(files []git.NiceTree, data map[string]any, rc *atreugo.RequestCtx) error { pageData := templates.PageData{ Meta: d.c.Meta, DisplayName: data["displayname"].(string), Name: data["name"].(string), Ref: data["ref"].(string), Description: data["desc"].(string), Parent: "", } if parent, ok := data["parent"]; ok && parent != nil { pageData.Parent = parent.(string) } readme := "" if readmeContent, ok := data["readme"]; ok && readmeContent != nil { readme = readmeContent.(string) } dotdot := "" if dotdotPath, ok := data["dotdot"]; ok && dotdotPath != nil { dotdot = dotdotPath.(string) } return templates.TreePage(pageData, files, readme, dotdot).Render(rc) } func countLines(r io.Reader) (int, error) { buf := make([]byte, 32*1024) bufLen := 0 count := 0 nl := []byte{'\n'} for { c, err := r.Read(buf) if c > 0 { bufLen += c } count += bytes.Count(buf[:c], nl) switch { case err == io.EOF: /* handle last line not having a newline at the end */ if bufLen >= 1 && buf[(bufLen-1)%(32*1024)] != '\n' { count++ } return count, nil case err != nil: return 0, err } } } func (d *deps) showFile(content string, data map[string]any, rc *atreugo.RequestCtx) error { var renderedContent string if len(content) > 0 { switch filepath.Ext(data["path"].(string)) { case ".md": unsafe := blackfriday.Run( []byte(content), blackfriday.WithExtensions(blackfriday.CommonExtensions), ) html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) renderedContent = string(html) default: safe := bluemonday.UGCPolicy().SanitizeBytes([]byte(content)) renderedContent = fmt.Sprintf(`
%s`, safe) } } lc, err := countLines(strings.NewReader(content)) if err != nil { // Non-fatal, we'll just skip showing line numbers in the template. log.Printf("counting lines: %s", err) } lines := make([]int, lc) if lc > 0 { for i := range lines { lines[i] = i + 1 } } pageData := templates.PageData{ Meta: d.c.Meta, DisplayName: getDisplayName(data["name"].(string)), LineCount: lines, Content: content, RenderedContent: renderedContent, Name: data["name"].(string), Ref: data["ref"].(string), Description: data["desc"].(string), Path: data["path"].(string), } return templates.FilePage(pageData).Render(rc) }