loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request '[UI] Do not include trailing EOL character when counting lines' (#4835) from gusted/forgejo-num-lines into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/4835
Reviewed-by: Caesar Schinas <caesar@caesarschinas.com>
Reviewed-by: Otto <otto@codeberg.org>

Gusted 7faea490 ecad5c9a

+88 -7
+2
options/locale/locale_en-US.ini
··· 1331 1331 line = line 1332 1332 lines = lines 1333 1333 from_comment = (comment) 1334 + no_eol.text = No EOL 1335 + no_eol.tooltip = This file doesn't contain a trailing end of line character. 1334 1336 1335 1337 editor.add_file = Add file 1336 1338 editor.new_file = New file
+11 -4
routers/web/repo/view.go
··· 560 560 // The Open Group Base Specification: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html 561 561 // empty: 0 lines; "a": 1 incomplete-line; "a\n": 1 line; "a\nb": 1 line, 1 incomplete-line; 562 562 // Forgejo uses the definition (like most modern editors): 563 - // empty: 0 lines; "a": 1 line; "a\n": 2 lines; "a\nb": 2 lines; 564 - // When rendering, the last empty line is not rendered in UI, while the line-number is still counted, to tell users that the file contains a trailing EOL. 565 - // To make the UI more consistent, it could use an icon mark to indicate that there is no trailing EOL, and show line-number as the rendered lines. 563 + // empty: 0 lines; "a": 1 line; "a\n": 1 line; "a\nb": 2 lines; 564 + // When rendering, the last empty line is not rendered in U and isn't counted towards the number of lines. 565 + // To tell users that the file not contains a trailing EOL, text with a tooltip is displayed in the file header. 566 566 // This NumLines is only used for the display on the UI: "xxx lines" 567 + hasTrailingEOL := bytes.HasSuffix(buf, []byte{'\n'}) 568 + ctx.Data["HasTrailingEOL"] = hasTrailingEOL 569 + ctx.Data["HasTrailingEOLSet"] = true 567 570 if len(buf) == 0 { 568 571 ctx.Data["NumLines"] = 0 569 572 } else { 570 - ctx.Data["NumLines"] = bytes.Count(buf, []byte{'\n'}) + 1 573 + numLines := bytes.Count(buf, []byte{'\n'}) 574 + if !hasTrailingEOL { 575 + numLines++ 576 + } 577 + ctx.Data["NumLines"] = numLines 571 578 } 572 579 ctx.Data["NumLinesSet"] = true 573 580
+5
templates/repo/file_info.tmpl
··· 9 9 {{.NumLines}} {{ctx.Locale.TrN .NumLines "repo.line" "repo.lines"}} 10 10 </div> 11 11 {{end}} 12 + {{if and .HasTrailingEOLSet (not .HasTrailingEOL)}} 13 + <div class="file-info-entry" data-tooltip-content="{{ctx.Locale.Tr "repo.no_eol.tooltip"}}"> 14 + {{ctx.Locale.Tr "repo.no_eol.text"}} 15 + </div> 16 + {{end}} 12 17 {{if .FileSize}} 13 18 <div class="file-info-entry"> 14 19 {{ctx.Locale.TrSize .FileSize}}{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}
+3 -3
tests/integration/linguist_test.go
··· 49 49 { 50 50 Operation: "create", 51 51 TreePath: "foo.c", 52 - ContentReader: strings.NewReader(`#include <stdio.h>\nint main() {\n printf("Hello world!\n");\n return 0;\n}\n`), 52 + ContentReader: strings.NewReader("#include <stdio.h>\nint main() {\n printf(\"Hello world!\n\");\n return 0;\n}\n"), 53 53 }, 54 54 { 55 55 Operation: "create", ··· 64 64 { 65 65 Operation: "create", 66 66 TreePath: "cpplint.py", 67 - ContentReader: strings.NewReader(`#! /usr/bin/env python\n\nprint("Hello world!")\n`), 67 + ContentReader: strings.NewReader("#! /usr/bin/env python\n\nprint(\"Hello world!\")\n"), 68 68 }, 69 69 { 70 70 Operation: "create", 71 71 TreePath: "some-file.xml", 72 - ContentReader: strings.NewReader(`<?xml version="1.0"?>\n<foo>\n <bar>Hello</bar>\n</foo>\n`), 72 + ContentReader: strings.NewReader("<?xml version=\"1.0\"?>\n<foo>\n <bar>Hello</bar>\n</foo>\n"), 73 73 }, 74 74 }) 75 75
+67
tests/integration/repo_view_test.go
··· 5 5 6 6 import ( 7 7 "fmt" 8 + "net/http" 8 9 "net/url" 9 10 "strings" 10 11 "testing" ··· 16 17 "code.gitea.io/gitea/services/context" 17 18 "code.gitea.io/gitea/services/contexttest" 18 19 files_service "code.gitea.io/gitea/services/repository/files" 20 + "code.gitea.io/gitea/tests" 19 21 20 22 "github.com/stretchr/testify/assert" 21 23 ) ··· 152 154 }) 153 155 }) 154 156 } 157 + 158 + func TestRepoViewFileLines(t *testing.T) { 159 + onGiteaRun(t, func(t *testing.T, _ *url.URL) { 160 + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 161 + repo, _, f := CreateDeclarativeRepo(t, user, "file-lines", []unit_model.Type{unit_model.TypeCode}, nil, []*files_service.ChangeRepoFile{ 162 + { 163 + Operation: "create", 164 + TreePath: "test-1", 165 + ContentReader: strings.NewReader("No newline"), 166 + }, 167 + { 168 + Operation: "create", 169 + TreePath: "test-2", 170 + ContentReader: strings.NewReader("No newline\n"), 171 + }, 172 + { 173 + Operation: "create", 174 + TreePath: "test-3", 175 + ContentReader: strings.NewReader("Two\nlines"), 176 + }, 177 + { 178 + Operation: "create", 179 + TreePath: "test-4", 180 + ContentReader: strings.NewReader("Really two\nlines\n"), 181 + }, 182 + }) 183 + defer f() 184 + 185 + t.Run("No EOL", func(t *testing.T) { 186 + defer tests.PrintCurrentTest(t)() 187 + 188 + req := NewRequest(t, "GET", repo.Link()+"/src/branch/main/test-1") 189 + resp := MakeRequest(t, req, http.StatusOK) 190 + htmlDoc := NewHTMLParser(t, resp.Body) 191 + 192 + fileInfo := htmlDoc.Find(".file-info").Text() 193 + assert.Contains(t, fileInfo, "No EOL") 194 + 195 + req = NewRequest(t, "GET", repo.Link()+"/src/branch/main/test-3") 196 + resp = MakeRequest(t, req, http.StatusOK) 197 + htmlDoc = NewHTMLParser(t, resp.Body) 198 + 199 + fileInfo = htmlDoc.Find(".file-info").Text() 200 + assert.Contains(t, fileInfo, "No EOL") 201 + }) 202 + 203 + t.Run("With EOL", func(t *testing.T) { 204 + defer tests.PrintCurrentTest(t)() 205 + 206 + req := NewRequest(t, "GET", repo.Link()+"/src/branch/main/test-2") 207 + resp := MakeRequest(t, req, http.StatusOK) 208 + htmlDoc := NewHTMLParser(t, resp.Body) 209 + 210 + fileInfo := htmlDoc.Find(".file-info").Text() 211 + assert.NotContains(t, fileInfo, "No EOL") 212 + 213 + req = NewRequest(t, "GET", repo.Link()+"/src/branch/main/test-4") 214 + resp = MakeRequest(t, req, http.StatusOK) 215 + htmlDoc = NewHTMLParser(t, resp.Body) 216 + 217 + fileInfo = htmlDoc.Find(".file-info").Text() 218 + assert.NotContains(t, fileInfo, "No EOL") 219 + }) 220 + }) 221 + }