Backport #16678 When files are highlighted the newline character needs to be added in a whitespace compliant mode. Also ensure the final empty newline is rendered. Fix #16434 Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
		
							parent
							
								
									62315ea731
								
							
						
					
					
						commit
						d89029ebac
					
				
					 2 changed files with 116 additions and 0 deletions
				
			
		|  | @ -166,6 +166,11 @@ func File(numLines int, fileName string, code []byte) map[int]string { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	htmlw.Flush() | 	htmlw.Flush() | ||||||
|  | 	finalNewLine := false | ||||||
|  | 	if len(code) > 0 { | ||||||
|  | 		finalNewLine = code[len(code)-1] == '\n' | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	m := make(map[int]string, numLines) | 	m := make(map[int]string, numLines) | ||||||
| 	for k, v := range strings.SplitN(htmlbuf.String(), "\n", numLines) { | 	for k, v := range strings.SplitN(htmlbuf.String(), "\n", numLines) { | ||||||
| 		line := k + 1 | 		line := k + 1 | ||||||
|  | @ -173,9 +178,17 @@ func File(numLines int, fileName string, code []byte) map[int]string { | ||||||
| 		//need to keep lines that are only \n so copy/paste works properly in browser
 | 		//need to keep lines that are only \n so copy/paste works properly in browser
 | ||||||
| 		if content == "" { | 		if content == "" { | ||||||
| 			content = "\n" | 			content = "\n" | ||||||
|  | 		} else if content == `</span><span class="w">` { | ||||||
|  | 			content += "\n</span>" | ||||||
| 		} | 		} | ||||||
|  | 		content = strings.TrimSuffix(content, `<span class="w">`) | ||||||
|  | 		content = strings.TrimPrefix(content, `</span>`) | ||||||
| 		m[line] = content | 		m[line] = content | ||||||
| 	} | 	} | ||||||
|  | 	if finalNewLine { | ||||||
|  | 		m[numLines+1] = "<span class=\"w\">\n</span>" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return m | 	return m | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										103
									
								
								modules/highlight/highlight_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								modules/highlight/highlight_test.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | ||||||
|  | // Copyright 2021 The Gitea Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a MIT-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package highlight | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"reflect" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"code.gitea.io/gitea/modules/setting" | ||||||
|  | 	"gopkg.in/ini.v1" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestFile(t *testing.T) { | ||||||
|  | 	setting.Cfg = ini.Empty() | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name     string | ||||||
|  | 		numLines int | ||||||
|  | 		fileName string | ||||||
|  | 		code     string | ||||||
|  | 		want     map[int]string | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:     ".drone.yml", | ||||||
|  | 			numLines: 12, | ||||||
|  | 			fileName: ".drone.yml", | ||||||
|  | 			code: `kind: pipeline | ||||||
|  | name: default | ||||||
|  | 
 | ||||||
|  | steps: | ||||||
|  | - name: test | ||||||
|  | 	image: golang:1.13 | ||||||
|  | 	environment: | ||||||
|  | 		GOPROXY: https://goproxy.cn
 | ||||||
|  | 	commands: | ||||||
|  | 	- go get -u | ||||||
|  | 	- go build -v | ||||||
|  | 	- go test -v -race -coverprofile=coverage.txt -covermode=atomic | ||||||
|  | `, | ||||||
|  | 			want: map[int]string{ | ||||||
|  | 				1: `<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">pipeline</span>`, | ||||||
|  | 				2: `<span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default</span>`, | ||||||
|  | 				3: `<span class="w"> | ||||||
|  | </span>`, | ||||||
|  | 				4: `<span class="w"></span><span class="nt">steps</span><span class="p">:</span>`, | ||||||
|  | 				5: `<span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test</span>`, | ||||||
|  | 				6: `<span class="w">	</span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">golang:1.13</span>`, | ||||||
|  | 				7: `<span class="w">	</span><span class="nt">environment</span><span class="p">:</span>`, | ||||||
|  | 				8: `<span class="w"></span><span class="w">		</span><span class="nt">GOPROXY</span><span class="p">:</span><span class="w"> </span><span class="l">https://goproxy.cn</span>`, | ||||||
|  | 				9: `<span class="w">	</span><span class="nt">commands</span><span class="p">:</span>`, | ||||||
|  | 				10: `<span class="w"></span><span class="w">	</span>- <span class="l">go get -u</span>`, | ||||||
|  | 				11: `<span class="w">	</span>- <span class="l">go build -v</span>`, | ||||||
|  | 				12: `<span class="w">	</span>- <span class="l">go test -v -race -coverprofile=coverage.txt -covermode=atomic</span><span class="w"> | ||||||
|  | </span>`, | ||||||
|  | 				13: `<span class="w"> | ||||||
|  | </span>`, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:     ".drone.yml - trailing space", | ||||||
|  | 			numLines: 13, | ||||||
|  | 			fileName: ".drone.yml", | ||||||
|  | 			code: `kind: pipeline | ||||||
|  | name: default  ` + ` | ||||||
|  | 
 | ||||||
|  | steps: | ||||||
|  | - name: test | ||||||
|  | 	image: golang:1.13 | ||||||
|  | 	environment: | ||||||
|  | 		GOPROXY: https://goproxy.cn
 | ||||||
|  | 	commands: | ||||||
|  | 	- go get -u | ||||||
|  | 	- go build -v | ||||||
|  | 	- go test -v -race -coverprofile=coverage.txt -covermode=atomic | ||||||
|  | 	`, | ||||||
|  | 			want: map[int]string{ | ||||||
|  | 				1: `<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">pipeline</span>`, | ||||||
|  | 				2: `<span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default  </span>`, | ||||||
|  | 				3: `<span class="w"> | ||||||
|  | </span>`, | ||||||
|  | 				4: `<span class="w"></span><span class="nt">steps</span><span class="p">:</span>`, | ||||||
|  | 				5: `<span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test</span>`, | ||||||
|  | 				6: `<span class="w">	</span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">golang:1.13</span>`, | ||||||
|  | 				7: `<span class="w">	</span><span class="nt">environment</span><span class="p">:</span>`, | ||||||
|  | 				8: `<span class="w"></span><span class="w">		</span><span class="nt">GOPROXY</span><span class="p">:</span><span class="w"> </span><span class="l">https://goproxy.cn</span>`, | ||||||
|  | 				9: `<span class="w">	</span><span class="nt">commands</span><span class="p">:</span>`, | ||||||
|  | 				10: `<span class="w"></span><span class="w">	</span>- <span class="l">go get -u</span>`, | ||||||
|  | 				11: `<span class="w">	</span>- <span class="l">go build -v</span>`, | ||||||
|  | 				12: `<span class="w">	</span>- <span class="l">go test -v -race -coverprofile=coverage.txt -covermode=atomic</span>`, | ||||||
|  | 				13: `<span class="w">	</span>`, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			if got := File(tt.numLines, tt.fileName, []byte(tt.code)); !reflect.DeepEqual(got, tt.want) { | ||||||
|  | 				t.Errorf("File() = %v, want %v", got, tt.want) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in a new issue