diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go index 75590b899b..993df717e1 100644 --- a/modules/markup/file_preview.go +++ b/modules/markup/file_preview.go @@ -35,24 +35,36 @@ type FilePreview struct { isTruncated bool } -func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Locale) *FilePreview { +func NewFilePreviews(ctx *RenderContext, node *html.Node, locale translation.Locale) []*FilePreview { if setting.FilePreviewMaxLines == 0 { // Feature is disabled return nil } + mAll := filePreviewPattern.FindAllStringSubmatchIndex(node.Data, -1) + if mAll == nil { + return nil + } + + result := make([]*FilePreview, 0) + + for _, m := range mAll { + if slices.Contains(m, -1) { + continue + } + + preview := newFilePreview(ctx, node, locale, m) + if preview != nil { + result = append(result, preview) + } + } + + return result +} + +func newFilePreview(ctx *RenderContext, node *html.Node, locale translation.Locale, m []int) *FilePreview { preview := &FilePreview{} - m := filePreviewPattern.FindStringSubmatchIndex(node.Data) - if m == nil { - return nil - } - - // Ensure that every group has a match - if slices.Contains(m, -1) { - return nil - } - urlFull := node.Data[m[0]:m[1]] // Ensure that we only use links to local repositories diff --git a/modules/markup/html.go b/modules/markup/html.go index e177fa3d74..8851558286 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -1073,28 +1073,34 @@ func filePreviewPatternProcessor(ctx *RenderContext, node *html.Node) { next := node.NextSibling for node != nil && node != next { - preview := NewFilePreview(ctx, node, locale) - if preview == nil { + previews := NewFilePreviews(ctx, node, locale) + if previews == nil { node = node.NextSibling continue } - previewNode := preview.CreateHTML(locale) + offset := 0 + for _, preview := range previews { + previewNode := preview.CreateHTML(locale) - // Specialized version of replaceContent, so the parent paragraph element is not destroyed from our div - before := node.Data[:preview.start] - after := node.Data[preview.end:] - node.Data = before - nextSibling := node.NextSibling - node.Parent.InsertBefore(&html.Node{ - Type: html.RawNode, - Data: "

", - }, nextSibling) - node.Parent.InsertBefore(previewNode, nextSibling) - node.Parent.InsertBefore(&html.Node{ - Type: html.RawNode, - Data: "

" + after, - }, nextSibling) + // Specialized version of replaceContent, so the parent paragraph element is not destroyed from our div + before := node.Data[:(preview.start - offset)] + after := node.Data[(preview.end - offset):] + offset += preview.end - 3 + node.Data = before + nextSibling := node.NextSibling + node.Parent.InsertBefore(&html.Node{ + Type: html.RawNode, + Data: "

", + }, nextSibling) + node.Parent.InsertBefore(previewNode, nextSibling) + afterNode := &html.Node{ + Type: html.RawNode, + Data: "

" + after, + } + node.Parent.InsertBefore(afterNode, nextSibling) + node = afterNode + } node = node.NextSibling } diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index bbf4f7d9e1..1b8a92e51f 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -828,6 +828,37 @@ func TestRender_FilePreview(t *testing.T) { `

`, localMetas, ) + + testRender( + "first without sub "+commitFilePreview+" second "+urlWithSub, + `

first without sub 190d949293/path/to/file.go (L2-L3) second

`+ + `
`+ + `
`+ + `
`+ + `path/to/file.go`+ + `
`+ + ``+ + `Lines 2 to 3 in 190d949`+ + ``+ + `
`+ + `
`+ + ``+ + ``+ + ``+ + ``+ + ``+ + ``+ + ``+ + ``+ + ``+ + ``+ + ``+ + `
B`+"\n"+`
C`+"\n"+`
`+ + `
`+ + `
`+ + `

`, + localMetas, + ) }) t.Run("multiples", func(t *testing.T) {