Fix #17514 Given the comments I've adjusted this somewhat. The numbers of characters detected are increased and include things like the use of U+300 to make à instead of à and non-breaking spaces. There is a button which can be used to escape the content to show it.
Showing the changes to services/gitdiff/gitdiff.go (1 of 26 files). Show all
Unified · Split
| @@ -169,11 +169,11 @@ func getDiffLineSectionInfo(treePath, line string, lastLeftIdx, lastRightIdx int · 168 unmodified lines | |||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | // escape a line's content or return <br> needed for copy/paste purposes | 171 | // escape a line's content or return <br> needed for copy/paste purposes |
| 172 | func getLineContent(content string) string { | 172 | func getLineContent(content string) DiffInline { |
| 173 | if len(content) > 0 { | 173 | if len(content) > 0 { |
| 174 | return html.EscapeString(content) | 174 | return DiffInlineWithUnicodeEscape(template.HTML(html.EscapeString(content))) |
| 175 | } | 175 | } |
| 176 | return "<br>" | 176 | return DiffInline{Content: "<br>"} |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | // DiffSection represents a section of a DiffFile. | 179 | // DiffSection represents a section of a DiffFile. |
| @@ -411,7 +411,7 @@ func fixupBrokenSpans(diffs []diffmatchpatch.Diff) []diffmatchpatch.Diff { · 231 unmodified lines | |||
| 411 | return fixedup | 411 | return fixedup |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | func diffToHTML(fileName string, diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML { | 414 | func diffToHTML(fileName string, diffs []diffmatchpatch.Diff, lineType DiffLineType) DiffInline { |
| 415 | buf := bytes.NewBuffer(nil) | 415 | buf := bytes.NewBuffer(nil) |
| 416 | match := "" | 416 | match := "" |
| 417 | 417 | ||
| @@ -483,7 +483,7 @@ func diffToHTML(fileName string, diffs []diffmatchpatch.Diff, lineType DiffLineT · 65 unmodified lines | |||
| 483 | buf.Write(codeTagSuffix) | 483 | buf.Write(codeTagSuffix) |
| 484 | } | 484 | } |
| 485 | } | 485 | } |
| 486 | return template.HTML(buf.Bytes()) | 486 | return DiffInlineWithUnicodeEscape(template.HTML(buf.String())) |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | // GetLine gets a specific line by type (add or del) and file line number | 489 | // GetLine gets a specific line by type (add or del) and file line number |
| @@ -535,10 +535,28 @@ func init() { · 45 unmodified lines | |||
| 535 | diffMatchPatch.DiffEditCost = 100 | 535 | diffMatchPatch.DiffEditCost = 100 |
| 536 | } | 536 | } |
| 537 | 537 | ||
| 538 | // DiffInline is a struct that has a content and escape status | ||
| 539 | type DiffInline struct { | ||
| 540 | EscapeStatus charset.EscapeStatus | ||
| 541 | Content template.HTML | ||
| 542 | } | ||
| 543 | |||
| 544 | // DiffInlineWithUnicodeEscape makes a DiffInline with hidden unicode characters escaped | ||
| 545 | func DiffInlineWithUnicodeEscape(s template.HTML) DiffInline { | ||
| 546 | status, content := charset.EscapeControlString(string(s)) | ||
| 547 | return DiffInline{EscapeStatus: status, Content: template.HTML(content)} | ||
| 548 | } | ||
| 549 | |||
| 550 | // DiffInlineWithHighlightCode makes a DiffInline with code highlight and hidden unicode characters escaped | ||
| 551 | func DiffInlineWithHighlightCode(fileName, language, code string) DiffInline { | ||
| 552 | status, content := charset.EscapeControlString(highlight.Code(fileName, language, code)) | ||
| 553 | return DiffInline{EscapeStatus: status, Content: template.HTML(content)} | ||
| 554 | } | ||
| 555 | |||
| 538 | // GetComputedInlineDiffFor computes inline diff for the given line. | 556 | // GetComputedInlineDiffFor computes inline diff for the given line. |
| 539 | func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) template.HTML { | 557 | func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) DiffInline { |
| 540 | if setting.Git.DisableDiffHighlight { | 558 | if setting.Git.DisableDiffHighlight { |
| 541 | return template.HTML(getLineContent(diffLine.Content[1:])) | 559 | return getLineContent(diffLine.Content[1:]) |
| 542 | } | 560 | } |
| 543 | 561 | ||
| 544 | var ( | 562 | var ( |
| @@ -555,26 +573,26 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) tem · 10 unmodified lines | |||
| 555 | // try to find equivalent diff line. ignore, otherwise | 573 | // try to find equivalent diff line. ignore, otherwise |
| 556 | switch diffLine.Type { | 574 | switch diffLine.Type { |
| 557 | case DiffLineSection: | 575 | case DiffLineSection: |
| 558 | return template.HTML(getLineContent(diffLine.Content[1:])) | 576 | return getLineContent(diffLine.Content[1:]) |
| 559 | case DiffLineAdd: | 577 | case DiffLineAdd: |
| 560 | compareDiffLine = diffSection.GetLine(DiffLineDel, diffLine.RightIdx) | 578 | compareDiffLine = diffSection.GetLine(DiffLineDel, diffLine.RightIdx) |
| 561 | if compareDiffLine == nil { | 579 | if compareDiffLine == nil { |
| 562 | return template.HTML(highlight.Code(diffSection.FileName, language, diffLine.Content[1:])) | 580 | return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:]) |
| 563 | } | 581 | } |
| 564 | diff1 = compareDiffLine.Content | 582 | diff1 = compareDiffLine.Content |
| 565 | diff2 = diffLine.Content | 583 | diff2 = diffLine.Content |
| 566 | case DiffLineDel: | 584 | case DiffLineDel: |
| 567 | compareDiffLine = diffSection.GetLine(DiffLineAdd, diffLine.LeftIdx) | 585 | compareDiffLine = diffSection.GetLine(DiffLineAdd, diffLine.LeftIdx) |
| 568 | if compareDiffLine == nil { | 586 | if compareDiffLine == nil { |
| 569 | return template.HTML(highlight.Code(diffSection.FileName, language, diffLine.Content[1:])) | 587 | return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:]) |
| 570 | } | 588 | } |
| 571 | diff1 = diffLine.Content | 589 | diff1 = diffLine.Content |
| 572 | diff2 = compareDiffLine.Content | 590 | diff2 = compareDiffLine.Content |
| 573 | default: | 591 | default: |
| 574 | if strings.IndexByte(" +-", diffLine.Content[0]) > -1 { | 592 | if strings.IndexByte(" +-", diffLine.Content[0]) > -1 { |
| 575 | return template.HTML(highlight.Code(diffSection.FileName, language, diffLine.Content[1:])) | 593 | return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:]) |
| 576 | } | 594 | } |
| 577 | return template.HTML(highlight.Code(diffSection.FileName, language, diffLine.Content)) | 595 | return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content) |
| 578 | } | 596 | } |
| 579 | 597 | ||
| 580 | diffRecord := diffMatchPatch.DiffMain(highlight.Code(diffSection.FileName, language, diff1[1:]), highlight.Code(diffSection.FileName, language, diff2[1:]), true) | 598 | diffRecord := diffMatchPatch.DiffMain(highlight.Code(diffSection.FileName, language, diff1[1:]), highlight.Code(diffSection.FileName, language, diff2[1:]), true) |