diff --git a/modules/markup/html_node.go b/modules/markup/html_node.go index f67437465c..4eb78fdd2b 100644 --- a/modules/markup/html_node.go +++ b/modules/markup/html_node.go @@ -63,8 +63,11 @@ func processNodeA(ctx *RenderContext, node *html.Node) { func visitNodeImg(ctx *RenderContext, img *html.Node) (next *html.Node) { next = img.NextSibling + attrSrc, hasLazy := "", false for i, imgAttr := range img.Attr { + hasLazy = hasLazy || imgAttr.Key == "loading" && imgAttr.Val == "lazy" if imgAttr.Key != "src" { + attrSrc = imgAttr.Val continue } @@ -72,8 +75,8 @@ func visitNodeImg(ctx *RenderContext, img *html.Node) (next *html.Node) { isLinkable := imgSrcOrigin != "" && !strings.HasPrefix(imgSrcOrigin, "data:") // By default, the "" tag should also be clickable, - // because frontend use `` to paste the re-scaled image into the markdown, - // so it must match the default markdown image behavior. + // because frontend uses `` to paste the re-scaled image into the Markdown, + // so it must match the default Markdown image behavior. cnt := 0 for p := img.Parent; isLinkable && p != nil && cnt < 2; p = p.Parent { if hasParentAnchor := p.Type == html.ElementNode && p.Data == "a"; hasParentAnchor { @@ -98,6 +101,9 @@ func visitNodeImg(ctx *RenderContext, img *html.Node) (next *html.Node) { imgAttr.Val = camoHandleLink(imgAttr.Val) img.Attr[i] = imgAttr } + if !RenderBehaviorForTesting.DisableAdditionalAttributes && !hasLazy && !strings.HasPrefix(attrSrc, "data:") { + img.Attr = append(img.Attr, html.Attribute{Key: "loading", Val: "lazy"}) + } return next } diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index 76434ac8b3..4eb01bcc2d 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -47,7 +47,7 @@ func TestRender_StandardLinks(t *testing.T) { func TestRender_Images(t *testing.T) { setting.AppURL = AppURL - test := func(input, expected string) { + render := func(input, expected string) { buffer, err := markdown.RenderString(markup.NewTestRenderContext(FullURL), input) assert.NoError(t, err) assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) @@ -59,27 +59,32 @@ func TestRender_Images(t *testing.T) { result := util.URLJoin(FullURL, url) // hint: With Markdown v2.5.2, there is a new syntax: [link](URL){:target="_blank"} , but we do not support it now - test( + render( "!["+title+"]("+url+")", `

`+title+`

`) - test( + render( "[["+title+"|"+url+"]]", `

`+title+`

`) - test( + render( "[!["+title+"]("+url+")]("+href+")", `

`+title+`

`) - test( + render( "!["+title+"]("+url+")", `

`+title+`

`) - test( + render( "[["+title+"|"+url+"]]", `

`+title+`

`) - test( + render( "[!["+title+"]("+url+")]("+href+")", `

`+title+`

`) + + defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, false)() + render( + "", // by the way, empty "a" tag will be removed + `

`) } func TestTotal_RenderString(t *testing.T) { diff --git a/modules/markup/sanitizer_default.go b/modules/markup/sanitizer_default.go index 14161eb533..9288be3b28 100644 --- a/modules/markup/sanitizer_default.go +++ b/modules/markup/sanitizer_default.go @@ -52,6 +52,8 @@ func (st *Sanitizer) createDefaultPolicy() *bluemonday.Policy { policy.AllowAttrs("src", "autoplay", "controls").OnElements("video") + policy.AllowAttrs("loading").OnElements("img") + // Allow generally safe attributes (reference: https://github.com/jch/html-pipeline) generalSafeAttrs := []string{ "abbr", "accept", "accept-charset", diff --git a/services/mailer/mail_test.go b/services/mailer/mail_test.go index 7a47cf3876..b15949f352 100644 --- a/services/mailer/mail_test.go +++ b/services/mailer/mail_test.go @@ -528,7 +528,7 @@ func TestEmbedBase64Images(t *testing.T) { require.NoError(t, err) mailBody := msgs[0].Body - assert.Regexp(t, `MSG-BEFORE ]+> MSG-AFTER`, mailBody) + assert.Regexp(t, `MSG-BEFORE ]+> MSG-AFTER`, mailBody) }) t.Run("EmbedInstanceImageSkipExternalImage", func(t *testing.T) { diff --git a/templates/repo/issue/card.tmpl b/templates/repo/issue/card.tmpl index 41fe6cea8f..9a8341dcca 100644 --- a/templates/repo/issue/card.tmpl +++ b/templates/repo/issue/card.tmpl @@ -4,7 +4,7 @@ {{if $attachments}}
{{range $attachments}} - {{.Name}} + {{.Name}} {{end}}
{{end}} diff --git a/templates/repo/issue/view_content/attachments.tmpl b/templates/repo/issue/view_content/attachments.tmpl index 2155f78656..e865050559 100644 --- a/templates/repo/issue/view_content/attachments.tmpl +++ b/templates/repo/issue/view_content/attachments.tmpl @@ -31,7 +31,7 @@ {{if FilenameIsImage .Name}} {{if not (StringUtils.Contains (StringUtils.ToString $.RenderedContent) .UUID)}} - {{.Name}} + {{.Name}} {{end}} {{end}} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 8f49bcf07e..e02111fd8e 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -615,7 +615,7 @@
- + {{svg "octicon-x" 16}} diff --git a/templates/repo/settings/lfs_file.tmpl b/templates/repo/settings/lfs_file.tmpl index 7698f77b2a..1a8014e218 100644 --- a/templates/repo/settings/lfs_file.tmpl +++ b/templates/repo/settings/lfs_file.tmpl @@ -21,7 +21,7 @@ {{else if not .IsTextFile}}
{{if .IsImageFile}} - {{$.RawFileLink}} + {{$.RawFileLink}} {{else if .IsVideoFile}}