1
1
mirror of https://github.com/go-gitea/gitea synced 2025-09-10 10:48:28 +00:00

Disable Field count validation of CSV viewer (#35228)

Default behaviour rejected all rows (Records) with more or fewer columns
(Fields) than the first row, preventing them from parsing at all and
silently hiding them. While RFC4180 section 2.4 says each line _should_
contain the same number of fields, enforcing this on the viewer is
unhelpful.
This pull request disables that validation, allowing the viewer to
render lines with fewer columns than the maximum number within the file.
As it's a simple HTML table, this works without additional changes (i.e.
no need to manually determine the maximum number of columns), but the
default appearance of rows with fewer columns may be undesirable to some
people, especially when using CSS that has `td {border-right: none}`.
<img width="1408" height="156" alt="Screenshot without cell right
borders"
src="https://github.com/user-attachments/assets/d4c19bbc-3fd2-4fd1-83a6-1125e953e95b"
/>
<img width="1397" height="158" alt="Screenshot with cell right borders"
src="https://github.com/user-attachments/assets/86aaafcb-d7e8-4228-99a8-7527c823a07c"
/>

Fixes #16559, #30358.

Unfortunately, retaining empty lines is less trivial, so the line
numbers on the leftmost column will still not match the source file
whenever those are present, though a future PR could address that.
This commit is contained in:
Luke H-W
2025-09-05 02:24:58 +09:30
committed by GitHub
parent 3e3c36bc30
commit 5fe3296055
2 changed files with 20 additions and 15 deletions

View File

@@ -30,6 +30,8 @@ func CreateReader(input io.Reader, delimiter rune) *stdcsv.Reader {
// thus would change `\t\t` to just `\t` or ` ` (two spaces) to just ` ` (single space) // thus would change `\t\t` to just `\t` or ` ` (two spaces) to just ` ` (single space)
rd.TrimLeadingSpace = true rd.TrimLeadingSpace = true
} }
// Don't force validation of every row to have the same number of entries as the first row.
rd.FieldsPerRecord = -1
return rd return rd
} }

View File

@@ -94,6 +94,24 @@ j, ,\x20
}, },
expectedDelimiter: ',', expectedDelimiter: ',',
}, },
// case 3 - every delimiter used, default to comma and handle differing number of fields per record
{
csv: `col1,col2
a;b
c@e
f g
h|i
jkl`,
expectedRows: [][]string{
{"col1", "col2"},
{"a;b"},
{"c@e"},
{"f g"},
{"h|i"},
{"jkl"},
},
expectedDelimiter: ',',
},
} }
for n, c := range cases { for n, c := range cases {
@@ -119,21 +137,6 @@ func TestDetermineDelimiterShortBufferError(t *testing.T) {
assert.Nil(t, rd, "CSV reader should be mnil") assert.Nil(t, rd, "CSV reader should be mnil")
} }
func TestDetermineDelimiterReadAllError(t *testing.T) {
rd, err := CreateReaderAndDetermineDelimiter(nil, strings.NewReader(`col1,col2
a;b
c@e
f g
h|i
jkl`))
assert.NoError(t, err, "CreateReaderAndDetermineDelimiter() shouldn't throw error")
assert.NotNil(t, rd, "CSV reader should not be mnil")
rows, err := rd.ReadAll()
assert.Error(t, err, "RaadAll() should throw error")
assert.ErrorIs(t, err, csv.ErrFieldCount)
assert.Empty(t, rows, "rows should be empty")
}
func TestDetermineDelimiter(t *testing.T) { func TestDetermineDelimiter(t *testing.T) {
cases := []struct { cases := []struct {
csv string csv string