Improve detecting empty files (#31332)

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
wxiaoguang 2024-06-13 09:06:46 +08:00 committed by GitHub
parent 7115dce773
commit 47ca61d8ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 29 additions and 13 deletions

View File

@ -1238,6 +1238,7 @@ file_view_rendered = View Rendered
file_view_raw = View Raw file_view_raw = View Raw
file_permalink = Permalink file_permalink = Permalink
file_too_large = The file is too large to be shown. file_too_large = The file is too large to be shown.
file_is_empty = The file is empty.
code_preview_line_from_to = Lines %[1]d to %[2]d in %[3]s code_preview_line_from_to = Lines %[1]d to %[2]d in %[3]s
code_preview_line_in = Line %[1]d in %[2]s code_preview_line_in = Line %[1]d in %[2]s
invisible_runes_header = `This file contains invisible Unicode characters` invisible_runes_header = `This file contains invisible Unicode characters`

View File

@ -99,8 +99,6 @@ func RefBlame(ctx *context.Context) {
} }
ctx.Data["NumLines"], err = blob.GetBlobLineCount() ctx.Data["NumLines"], err = blob.GetBlobLineCount()
ctx.Data["NumLinesSet"] = true
if err != nil { if err != nil {
ctx.NotFound("GetBlobLineCount", err) ctx.NotFound("GetBlobLineCount", err)
return return

View File

@ -303,6 +303,7 @@ func LFSFileGet(ctx *context.Context) {
rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc), charset.ConvertOpts{}) rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc), charset.ConvertOpts{})
// Building code view blocks with line number on server side. // Building code view blocks with line number on server side.
// FIXME: the logic is not right here: it first calls EscapeControlReader then calls HTMLEscapeString: double-escaping
escapedContent := &bytes.Buffer{} escapedContent := &bytes.Buffer{}
ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, escapedContent, ctx.Locale) ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, escapedContent, ctx.Locale)

View File

@ -286,6 +286,7 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr
ctx.Data["FileIsText"] = fInfo.isTextFile ctx.Data["FileIsText"] = fInfo.isTextFile
ctx.Data["FileName"] = path.Join(subfolder, readmeFile.Name()) ctx.Data["FileName"] = path.Join(subfolder, readmeFile.Name())
ctx.Data["FileSize"] = fInfo.fileSize
ctx.Data["IsLFSFile"] = fInfo.isLFSFile ctx.Data["IsLFSFile"] = fInfo.isLFSFile
if fInfo.isLFSFile { if fInfo.isLFSFile {
@ -301,7 +302,6 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr
// Pretend that this is a normal text file to display 'This file is too large to be shown' // Pretend that this is a normal text file to display 'This file is too large to be shown'
ctx.Data["IsFileTooLarge"] = true ctx.Data["IsFileTooLarge"] = true
ctx.Data["IsTextFile"] = true ctx.Data["IsTextFile"] = true
ctx.Data["FileSize"] = fInfo.fileSize
return return
} }
@ -552,7 +552,6 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry) {
} else { } else {
ctx.Data["NumLines"] = bytes.Count(buf, []byte{'\n'}) + 1 ctx.Data["NumLines"] = bytes.Count(buf, []byte{'\n'}) + 1
} }
ctx.Data["NumLinesSet"] = true
language, err := files_service.TryGetContentLanguage(ctx.Repo.GitRepo, ctx.Repo.CommitID, ctx.Repo.TreePath) language, err := files_service.TryGetContentLanguage(ctx.Repo.GitRepo, ctx.Repo.CommitID, ctx.Repo.TreePath)
if err != nil { if err != nil {
@ -606,8 +605,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry) {
break break
} }
// TODO: this logic seems strange, it duplicates with "isRepresentableAsText=true", it is not the same as "LFSFileGet" in "lfs.go" // TODO: this logic duplicates with "isRepresentableAsText=true", it is not the same as "LFSFileGet" in "lfs.go"
// maybe for this case, the file is a binary file, and shouldn't be rendered? // It is used by "external renders", markupRender will execute external programs to get rendered content.
if markupType := markup.Type(blob.Name()); markupType != "" { if markupType := markup.Type(blob.Name()); markupType != "" {
rd := io.MultiReader(bytes.NewReader(buf), dataRc) rd := io.MultiReader(bytes.NewReader(buf), dataRc)
ctx.Data["IsMarkup"] = true ctx.Data["IsMarkup"] = true

View File

@ -32,6 +32,8 @@
<div class="file-view code-view unicode-escaped"> <div class="file-view code-view unicode-escaped">
{{if .IsFileTooLarge}} {{if .IsFileTooLarge}}
{{template "shared/filetoolarge" dict "RawFileLink" .RawFileLink}} {{template "shared/filetoolarge" dict "RawFileLink" .RawFileLink}}
{{else if not .FileSize}}
{{template "shared/fileisempty"}}
{{else}} {{else}}
<table> <table>
<tbody> <tbody>

View File

@ -4,12 +4,12 @@
{{ctx.Locale.Tr "repo.symbolic_link"}} {{ctx.Locale.Tr "repo.symbolic_link"}}
</div> </div>
{{end}} {{end}}
{{if .NumLinesSet}}{{/* Explicit attribute needed to show 0 line changes */}} {{if ne .NumLines nil}}
<div class="file-info-entry"> <div class="file-info-entry">
{{.NumLines}} {{ctx.Locale.TrN .NumLines "repo.line" "repo.lines"}} {{.NumLines}} {{ctx.Locale.TrN .NumLines "repo.line" "repo.lines"}}
</div> </div>
{{end}} {{end}}
{{if .FileSize}} {{if ne .FileSize nil}}
<div class="file-info-entry"> <div class="file-info-entry">
{{FileSize .FileSize}}{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}} {{FileSize .FileSize}}{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}
</div> </div>

View File

@ -16,10 +16,8 @@
<div class="file-view{{if .IsMarkup}} markup {{.MarkupType}}{{else if .IsPlainText}} plain-text{{else if .IsTextFile}} code-view{{end}}"> <div class="file-view{{if .IsMarkup}} markup {{.MarkupType}}{{else if .IsPlainText}} plain-text{{else if .IsTextFile}} code-view{{end}}">
{{if .IsFileTooLarge}} {{if .IsFileTooLarge}}
{{template "shared/filetoolarge" dict "RawFileLink" .RawFileLink}} {{template "shared/filetoolarge" dict "RawFileLink" .RawFileLink}}
{{else if .IsMarkup}} {{else if not .FileSize}}
{{if .FileContent}}{{.FileContent | SafeHTML}}{{end}} {{template "shared/fileisempty"}}
{{else if .IsPlainText}}
<pre>{{if .FileContent}}{{.FileContent | SafeHTML}}{{end}}</pre>
{{else if not .IsTextFile}} {{else if not .IsTextFile}}
<div class="view-raw"> <div class="view-raw">
{{if .IsImageFile}} {{if .IsImageFile}}

View File

@ -91,6 +91,8 @@
<div class="file-view{{if .IsMarkup}} markup {{.MarkupType}}{{else if .IsPlainText}} plain-text{{else if .IsTextSource}} code-view{{end}}"> <div class="file-view{{if .IsMarkup}} markup {{.MarkupType}}{{else if .IsPlainText}} plain-text{{else if .IsTextSource}} code-view{{end}}">
{{if .IsFileTooLarge}} {{if .IsFileTooLarge}}
{{template "shared/filetoolarge" dict "RawFileLink" .RawFileLink}} {{template "shared/filetoolarge" dict "RawFileLink" .RawFileLink}}
{{else if not .FileSize}}
{{template "shared/fileisempty"}}
{{else if .IsMarkup}} {{else if .IsMarkup}}
{{if .FileContent}}{{.FileContent}}{{end}} {{if .FileContent}}{{.FileContent}}{{end}}
{{else if .IsPlainText}} {{else if .IsPlainText}}

View File

@ -0,0 +1,3 @@
<div class="file-not-rendered-prompt">
{{ctx.Locale.Tr "repo.file_is_empty"}}
</div>

View File

@ -1,4 +1,4 @@
<div class="tw-p-4"> <div class="file-not-rendered-prompt">
{{ctx.Locale.Tr "repo.file_too_large"}} {{ctx.Locale.Tr "repo.file_too_large"}}
{{if .RawFileLink}}<a href="{{.RawFileLink}}" rel="nofollow">{{ctx.Locale.Tr "repo.file_view_raw"}}</a>{{end}} {{if .RawFileLink}}<a href="{{.RawFileLink}}" rel="nofollow">{{ctx.Locale.Tr "repo.file_view_raw"}}</a>{{end}}
</div> </div>

View File

@ -1706,6 +1706,18 @@ td .commit-summary {
.file-view.markup { .file-view.markup {
padding: 1em 2em; padding: 1em 2em;
} }
.file-view.markup:has(.file-not-rendered-prompt) {
padding: 0; /* let the file-not-rendered-prompt layout itself */
}
.file-not-rendered-prompt {
padding: 1rem;
text-align: center;
font-size: 1rem !important; /* use consistent styles for various containers (code, markup, etc) */
line-height: var(--line-height-default) !important; /* same as above */
}
.repository .activity-header { .repository .activity-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;