History

Server-side syntax highlighting for all code (#12047)

* Server-side syntax hilighting for all code This PR does a few things: * Remove all traces of highlight.js * Use chroma library to provide fast syntax hilighting directly on the server * Provide syntax hilighting for diffs * Re-style both unified and split diffs views * Add custom syntax hilighting styling for both regular and arc-green Fixes #7729 Fixes #10157 Fixes #11825 Fixes #7728 Fixes #3872 Fixes #3682 And perhaps gets closer to #9553 * fix line marker * fix repo search * Fix single line select * properly load settings * npm uninstall highlight.js * review suggestion * code review * forgot to call function * fix test * Apply suggestions from code review suggestions from @silverwind thanks Co-authored-by: silverwind <me@silverwind.io> * code review * copy/paste error * Use const for highlight size limit * Update web_src/less/_repository.less Co-authored-by: Lauris BH <lauris@nix.lv> * update size limit to 1MB and other styling tweaks * fix highlighting for certain diff sections * fix test * add worker back as suggested

mrsdizzie committed 6 years ago

Commit af7ffaa1 parent ce5f2b9336 files · +37289 −765Browse files

Showing the changes to services/gitdiff/gitdiff.go (1 of 336 files). Show all

Unified · Split

services/gitdiff/gitdiff.go+23−24
@@ -10,7 +10,6 @@ import ( · 9 unmodified lines
10 "bytes"10 "bytes"
11 "context"11 "context"
12 "fmt"12 "fmt"
13 "html"
14 "html/template"13 "html/template"
15 "io"14 "io"
16 "io/ioutil"15 "io/ioutil"
@@ -164,15 +163,16 @@ func getDiffLineSectionInfo(treePath, line string, lastLeftIdx, lastRightIdx int · 147 unmodified lines
164// escape a line's content or return <br> needed for copy/paste purposes163// escape a line's content or return <br> needed for copy/paste purposes
165func getLineContent(content string) string {164func getLineContent(content string) string {
166 if len(content) > 0 {165 if len(content) > 0 {
167 return html.EscapeString(content)166 return content
168 }167 }
169 return "<br>"168 return "\n"
170}169}
171 170
172// DiffSection represents a section of a DiffFile.171// DiffSection represents a section of a DiffFile.
173type DiffSection struct {172type DiffSection struct {
174 Name string173 FileName string
175 Lines []*DiffLine174 Name string
175 Lines []*DiffLine
176}176}
177 177
178var (178var (
@@ -181,24 +181,23 @@ var ( · 2 unmodified lines
181 codeTagSuffix = []byte(`</span>`)181 codeTagSuffix = []byte(`</span>`)
182)182)
183 183
184func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML {184func diffToHTML(fileName string, diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML {
185 buf := bytes.NewBuffer(nil)185 buf := bytes.NewBuffer(nil)
186 186
187 for i := range diffs {187 for i := range diffs {
188 switch {188 switch {
189 case diffs[i].Type == diffmatchpatch.DiffInsert && lineType == DiffLineAdd:189 case diffs[i].Type == diffmatchpatch.DiffInsert && lineType == DiffLineAdd:
190 buf.Write(addedCodePrefix)190 buf.Write(addedCodePrefix)
191 buf.WriteString(getLineContent(diffs[i].Text))191 buf.WriteString(highlight.Code(fileName, diffs[i].Text))
192 buf.Write(codeTagSuffix)192 buf.Write(codeTagSuffix)
193 case diffs[i].Type == diffmatchpatch.DiffDelete && lineType == DiffLineDel:193 case diffs[i].Type == diffmatchpatch.DiffDelete && lineType == DiffLineDel:
194 buf.Write(removedCodePrefix)194 buf.Write(removedCodePrefix)
195 buf.WriteString(getLineContent(diffs[i].Text))195 buf.WriteString(highlight.Code(fileName, diffs[i].Text))
196 buf.Write(codeTagSuffix)196 buf.Write(codeTagSuffix)
197 case diffs[i].Type == diffmatchpatch.DiffEqual:197 case diffs[i].Type == diffmatchpatch.DiffEqual:
198 buf.WriteString(getLineContent(diffs[i].Text))198 buf.WriteString(highlight.Code(fileName, getLineContent(diffs[i].Text)))
199 }199 }
200 }200 }
201
202 return template.HTML(buf.Bytes())201 return template.HTML(buf.Bytes())
203}202}
204 203
@@ -256,6 +255,7 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) tem · 51 unmodified lines
256 if setting.Git.DisableDiffHighlight {255 if setting.Git.DisableDiffHighlight {
257 return template.HTML(getLineContent(diffLine.Content[1:]))256 return template.HTML(getLineContent(diffLine.Content[1:]))
258 }257 }
258
259 var (259 var (
260 compareDiffLine *DiffLine260 compareDiffLine *DiffLine
261 diff1 string261 diff1 string
@@ -264,31 +264,32 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) tem · 2 unmodified lines
264 264
265 // try to find equivalent diff line. ignore, otherwise265 // try to find equivalent diff line. ignore, otherwise
266 switch diffLine.Type {266 switch diffLine.Type {
267 case DiffLineSection:
268 return template.HTML(getLineContent(diffLine.Content[1:]))
267 case DiffLineAdd:269 case DiffLineAdd:
268 compareDiffLine = diffSection.GetLine(DiffLineDel, diffLine.RightIdx)270 compareDiffLine = diffSection.GetLine(DiffLineDel, diffLine.RightIdx)
269 if compareDiffLine == nil {271 if compareDiffLine == nil {
270 return template.HTML(getLineContent(diffLine.Content[1:]))272 return template.HTML(highlight.Code(diffSection.FileName, diffLine.Content[1:]+"\n"))
271 }273 }
272 diff1 = compareDiffLine.Content274 diff1 = compareDiffLine.Content
273 diff2 = diffLine.Content275 diff2 = diffLine.Content
274 case DiffLineDel:276 case DiffLineDel:
275 compareDiffLine = diffSection.GetLine(DiffLineAdd, diffLine.LeftIdx)277 compareDiffLine = diffSection.GetLine(DiffLineAdd, diffLine.LeftIdx)
276 if compareDiffLine == nil {278 if compareDiffLine == nil {
277 return template.HTML(getLineContent(diffLine.Content[1:]))279 return template.HTML(highlight.Code(diffSection.FileName, diffLine.Content[1:]+"\n"))
278 }280 }
279 diff1 = diffLine.Content281 diff1 = diffLine.Content
280 diff2 = compareDiffLine.Content282 diff2 = compareDiffLine.Content
281 default:283 default:
282 if strings.IndexByte(" +-", diffLine.Content[0]) > -1 {284 if strings.IndexByte(" +-", diffLine.Content[0]) > -1 {
283 return template.HTML(getLineContent(diffLine.Content[1:]))285 return template.HTML(highlight.Code(diffSection.FileName, diffLine.Content[1:]+"\n"))
284 }286 }
285 return template.HTML(getLineContent(diffLine.Content))287 return template.HTML(highlight.Code(diffSection.FileName, diffLine.Content))
286 }288 }
287 289
288 diffRecord := diffMatchPatch.DiffMain(diff1[1:], diff2[1:], true)290 diffRecord := diffMatchPatch.DiffMain(diff1[1:], diff2[1:], true)
289 diffRecord = diffMatchPatch.DiffCleanupEfficiency(diffRecord)291 diffRecord = diffMatchPatch.DiffCleanupEfficiency(diffRecord)
290 292 return diffToHTML(diffSection.FileName, diffRecord, diffLine.Type)
291 return diffToHTML(diffRecord, diffLine.Type)
292}293}
293 294
294// DiffFile represents a file diff.295// DiffFile represents a file diff.
@@ -313,11 +314,6 @@ func (diffFile *DiffFile) GetType() int { · 18 unmodified lines
313 return int(diffFile.Type)314 return int(diffFile.Type)
314}315}
315 316
316// GetHighlightClass returns highlight class for a filename.
317func (diffFile *DiffFile) GetHighlightClass() string {
318 return highlight.FileNameToHighlightClass(diffFile.Name)
319}
320
321// GetTailSection creates a fake DiffLineSection if the last section is not the end of the file317// GetTailSection creates a fake DiffLineSection if the last section is not the end of the file
322func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommitID, rightCommitID string) *DiffSection {318func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommitID, rightCommitID string) *DiffSection {
323 if len(diffFile.Sections) == 0 || diffFile.Type != DiffFileChange || diffFile.IsBin || diffFile.IsLFSFile {319 if len(diffFile.Sections) == 0 || diffFile.Type != DiffFileChange || diffFile.IsBin || diffFile.IsLFSFile {
@@ -348,7 +344,7 @@ func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommitID, · 24 unmodified lines
348 LeftIdx: leftLineCount,344 LeftIdx: leftLineCount,
349 RightIdx: rightLineCount,345 RightIdx: rightLineCount,
350 }}346 }}
351 tailSection := &DiffSection{Lines: []*DiffLine{tailDiffLine}}347 tailSection := &DiffSection{FileName: diffFile.Name, Lines: []*DiffLine{tailDiffLine}}
352 return tailSection348 return tailSection
353 349
354}350}
@@ -405,8 +401,7 @@ const cmdDiffHead = "diff --git " · 50 unmodified lines
405// TODO: move this function to gogits/git-module401// TODO: move this function to gogits/git-module
406func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*Diff, error) {402func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*Diff, error) {
407 var (403 var (
408 diff = &Diff{Files: make([]*DiffFile, 0)}404 diff = &Diff{Files: make([]*DiffFile, 0)}
409
410 curFile = &DiffFile{}405 curFile = &DiffFile{}
411 curSection = &DiffSection{406 curSection = &DiffSection{
412 Lines: make([]*DiffLine, 0, 10),407 Lines: make([]*DiffLine, 0, 10),
@@ -481,6 +476,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 68 unmodified lines
481 leftLine++476 leftLine++
482 rightLine++477 rightLine++
483 curSection.Lines = append(curSection.Lines, diffLine)478 curSection.Lines = append(curSection.Lines, diffLine)
479 curSection.FileName = curFile.Name
484 continue480 continue
485 case line[0] == '@':481 case line[0] == '@':
486 curSection = &DiffSection{}482 curSection = &DiffSection{}
@@ -492,6 +488,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 5 unmodified lines
492 SectionInfo: lineSectionInfo,488 SectionInfo: lineSectionInfo,
493 }489 }
494 curSection.Lines = append(curSection.Lines, diffLine)490 curSection.Lines = append(curSection.Lines, diffLine)
491 curSection.FileName = curFile.Name
495 // update line number.492 // update line number.
496 leftLine = lineSectionInfo.LeftIdx493 leftLine = lineSectionInfo.LeftIdx
497 rightLine = lineSectionInfo.RightIdx494 rightLine = lineSectionInfo.RightIdx
@@ -502,6 +499,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 4 unmodified lines
502 diffLine := &DiffLine{Type: DiffLineAdd, Content: line, RightIdx: rightLine}499 diffLine := &DiffLine{Type: DiffLineAdd, Content: line, RightIdx: rightLine}
503 rightLine++500 rightLine++
504 curSection.Lines = append(curSection.Lines, diffLine)501 curSection.Lines = append(curSection.Lines, diffLine)
502 curSection.FileName = curFile.Name
505 continue503 continue
506 case line[0] == '-':504 case line[0] == '-':
507 curFile.Deletion++505 curFile.Deletion++
@@ -511,6 +509,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 3 unmodified lines
511 leftLine++509 leftLine++
512 }510 }
513 curSection.Lines = append(curSection.Lines, diffLine)511 curSection.Lines = append(curSection.Lines, diffLine)
512 curSection.FileName = curFile.Name
514 case strings.HasPrefix(line, "Binary"):513 case strings.HasPrefix(line, "Binary"):
515 curFile.IsBin = true514 curFile.IsBin = true
516 continue515 continue