diff --git a/modules/markup/html.go b/modules/markup/html.go index 58021f5cb5..83ce87aea4 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -1078,12 +1078,15 @@ func filePreviewPatternProcessor(ctx *RenderContext, node *html.Node) { next := node.NextSibling for node != nil && node != next { + if node.Parent == nil || node.Parent.Type != html.ElementNode { + node = node.NextSibling + continue + } previews := NewFilePreviews(ctx, node, locale) if previews == nil { node = node.NextSibling continue } - offset := 0 for _, preview := range previews { previewNode := preview.CreateHTML(locale) @@ -1091,23 +1094,41 @@ func filePreviewPatternProcessor(ctx *RenderContext, node *html.Node) { // 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):] - afterPrefix := "

" - offset = preview.end - len(afterPrefix) - 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: afterPrefix + after, + Type: html.TextNode, + Data: after, + } + matched := true + switch node.Parent.Data { + case "div", "li", "td", "th", "details": + nextSibling := node.NextSibling + node.Parent.InsertBefore(previewNode, nextSibling) + node.Parent.InsertBefore(afterNode, nextSibling) + case "p", "span", "em", "strong": + nextSibling := node.Parent.NextSibling + node.Parent.Parent.InsertBefore(previewNode, nextSibling) + afterPNode := &html.Node{ + Type: html.ElementNode, + Data: node.Parent.Data, + Attr: node.Parent.Attr, + } + afterPNode.AppendChild(afterNode) + node.Parent.Parent.InsertBefore(afterPNode, nextSibling) + siblingNode := node.NextSibling + if siblingNode != nil { + node.NextSibling = nil + siblingNode.PrevSibling = nil + afterPNode.AppendChild(siblingNode) + } + default: + matched = false + } + if matched { + offset = preview.end + node.Data = before + node = afterNode } - 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 11a6290ca3..cd235331bc 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -1181,32 +1181,75 @@ func TestRender_FilePreview(t *testing.T) { }) commitFileURL = util.URLJoin(markup.TestRepoURL, "src", "commit", "eeb243c3395e1921c5d90e73bd739827251fc99d", "path", "to", "file%20%23.txt") + commitFileURLFirstLine := commitFileURL + "#L1" + filePreviewBox := `
` + + `
` + + `
` + + `path/to/file #.txt` + + `
` + + `` + + `Line 1 in eeb243c` + + `` + + `
` + + `
` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `
A` + "\n" + `
` + + `
` + + `
` + linkRendered := `eeb243c339/path/to/file%20%23.txt (L1)` t.Run("file with strange characters in name", func(t *testing.T) { testRender( - commitFileURL+"#L1", - `

`+ - `
`+ - `
`+ - `
`+ - `path/to/file #.txt`+ - `
`+ - ``+ - `Line 1 in eeb243c`+ - ``+ - `
`+ - `
`+ - ``+ - ``+ - ``+ - ``+ - ``+ - ``+ - ``+ - `
A`+"\n"+`
`+ - `
`+ - `
`+ - `

`, + commitFileURLFirstLine, + `

`+filePreviewBox+`

`, + localMetas, + ) + }) + + t.Run("file preview with stuff before and after", func(t *testing.T) { + testRender( + ":frog: before"+commitFileURLFirstLine+" :frog: after", + `

🐸 before

`+ + filePreviewBox+ + `

🐸 after

`, + localMetas, + ) + }) + + t.Run("file preview in
,
  • ,
    (not in ) environments", func(t *testing.T) { + testRender( + "
    "+commitFileURLFirstLine+"
    \n"+ + "
    • "+commitFileURLFirstLine+"
    \n"+ + "
    "+commitFileURLFirstLine+""+commitFileURLFirstLine+"
    ", + `
    `+filePreviewBox+`
    `+"\n"+ + `
    • `+filePreviewBox+`
    `+"\n"+ + `
    `+linkRendered+``+filePreviewBox+`
    `, + localMetas, + ) + }) + + t.Run("file preview in , and environments", func(t *testing.T) { + testRender( + "
    "+commitFileURLFirstLine+" "+commitFileURLFirstLine+" "+commitFileURLFirstLine+"
    ", + `
    `+filePreviewBox+` `+ + ``+filePreviewBox+` `+ + ``+filePreviewBox+`
    `, + localMetas, + ) + }) + + t.Run("no file preview in heading, striked out, code environments", func(t *testing.T) { + testRender( + "

    "+commitFileURLFirstLine+"

    \n"+commitFileURLFirstLine+"\n"+commitFileURLFirstLine+"", + `

    `+linkRendered+`

    `+"\n"+ + ``+linkRendered+``+"\n"+ + ``+commitFileURLFirstLine+``, localMetas, ) })