From ae0615561a9b9a4010a0ef815eef04ae2de24541 Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Fri, 19 Apr 2024 18:21:21 +0200
Subject: [PATCH] Fix issue where rendering stops after the first invalid
parmalink
(cherry picked from commit e9eacdecd20602887adc5ad254bcc4678ee1a94d)
---
modules/markup/file_preview.go | 34 +++++++++++++++++++----------
modules/markup/html.go | 40 +++++++++++++++++++---------------
modules/markup/html_test.go | 31 ++++++++++++++++++++++++++
3 files changed, 77 insertions(+), 28 deletions(-)
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
`+
+ ``+
+ ``+
+ `
`+
+ `
`+
+ ``+
+ ``+
+ ` | `+
+ `B`+"\n"+` | `+
+ `
`+
+ ``+
+ ` | `+
+ `C`+"\n"+` | `+
+ `
`+
+ ``+
+ `
`+
+ `
`+
+ `
`+
+ ``,
+ localMetas,
+ )
})
t.Run("multiples", func(t *testing.T) {