Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix rendered wiki page link #31398

Merged
merged 2 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 3 additions & 24 deletions modules/markup/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,10 +748,10 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
if image {
link = strings.ReplaceAll(link, " ", "+")
} else {
link = strings.ReplaceAll(link, " ", "-")
link = strings.ReplaceAll(link, " ", "-") // FIXME: it should support dashes in the link, eg: "the-dash-support.-"
}
if !strings.Contains(link, "/") {
link = url.PathEscape(link)
link = url.PathEscape(link) // FIXME: it doesn't seem right and it might cause double-escaping
}
}
if image {
Expand Down Expand Up @@ -783,28 +783,7 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
childNode.Attr = childNode.Attr[:2]
}
} else {
if !absoluteLink {
var base string
if ctx.IsWiki {
switch ext {
case "":
// no file extension, create a regular wiki link
base = ctx.Links.WikiLink()
default:
// we have a file extension:
// return a regular wiki link if it's a renderable file (extension),
// raw link otherwise
if Type(link) != "" {
base = ctx.Links.WikiLink()
} else {
base = ctx.Links.WikiRawLink()
}
}
} else {
base = ctx.Links.SrcLink()
}
link = util.URLJoin(base, link)
}
link, _ = ResolveLink(ctx, link, "")
childNode.Type = html.TextNode
childNode.Data = name
}
Expand Down
35 changes: 35 additions & 0 deletions modules/markup/html_link.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package markup

import (
"path"

"code.gitea.io/gitea/modules/util"
)

func ResolveLink(ctx *RenderContext, link, userContentAnchorPrefix string) (result string, resolved bool) {
isAnchorFragment := link != "" && link[0] == '#'
if !isAnchorFragment && !IsFullURLString(link) {
linkBase := ctx.Links.Base
if ctx.IsWiki {
if ext := path.Ext(link); ext == "" || ext == ".-" {
linkBase = ctx.Links.WikiLink() // the link is for a wiki page
} else if DetectMarkupTypeByFileName(link) != "" {
linkBase = ctx.Links.WikiLink() // the link is renderable as a wiki page
} else {
linkBase = ctx.Links.WikiRawLink() // otherwise, use a raw link instead to view&download medias
}
} else if ctx.Links.BranchPath != "" || ctx.Links.TreePath != "" {
// if there is no BranchPath, then the link will be something like "/owner/repo/src/{the-file-path}"
// and then this link will be handled by the "legacy-ref" code and be redirected to the default branch like "/owner/repo/src/branch/main/{the-file-path}"
linkBase = ctx.Links.SrcLink()
}
link, resolved = util.URLJoin(linkBase, link), true
}
if isAnchorFragment && userContentAnchorPrefix != "" {
link, resolved = userContentAnchorPrefix+link[1:], true
}
return link, resolved
}
4 changes: 4 additions & 0 deletions modules/markup/html_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ func TestRender_ShortLinks(t *testing.T) {
"[[Link]]",
`<p><a href="`+url+`" rel="nofollow">Link</a></p>`,
`<p><a href="`+urlWiki+`" rel="nofollow">Link</a></p>`)
test(
"[[Link.-]]",
`<p><a href="http://localhost:3000/test-owner/test-repo/src/master/Link.-" rel="nofollow">Link.-</a></p>`,
`<p><a href="http://localhost:3000/test-owner/test-repo/wiki/Link.-" rel="nofollow">Link.-</a></p>`)
test(
"[[Link.jpg]]",
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Link.jpg" alt="Link.jpg"/></a></p>`,
Expand Down
10 changes: 5 additions & 5 deletions modules/markup/markdown/markdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ [email protected]
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/src/file.bin" rel="nofollow">local link</a><br/>
<a href="/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/image.jpg" target="_blank" rel="nofollow noopener"><img src="/image.jpg" alt="local image"/></a><br/>
<a href="/path/file" target="_blank" rel="nofollow noopener"><img src="/path/file" alt="local image"/></a><br/>
Expand Down Expand Up @@ -691,7 +691,7 @@ space</p>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="https://gitea.io/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="https://gitea.io/src/file.bin" rel="nofollow">local link</a><br/>
<a href="https://gitea.io/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="https://gitea.io/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/image.jpg" alt="local image"/></a><br/>
<a href="https://gitea.io/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/path/file" alt="local image"/></a><br/>
Expand Down Expand Up @@ -749,7 +749,7 @@ space</p>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/relative/path/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/src/file.bin" rel="nofollow">local link</a><br/>
<a href="/relative/path/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/image.jpg" alt="local image"/></a><br/>
<a href="/relative/path/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/path/file" alt="local image"/></a><br/>
Expand Down Expand Up @@ -866,7 +866,7 @@ space</p>
Expected: `<p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/user/repo/file.bin" rel="nofollow">local link</a><br/>
<a href="/user/repo/src/sub/folder/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/user/repo/src/sub/folder/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
Expand Down Expand Up @@ -984,7 +984,7 @@ space</p>
for i, c := range cases {
result, err := markdown.RenderString(&markup.RenderContext{Ctx: context.Background(), Links: c.Links, IsWiki: c.IsWiki}, input)
assert.NoError(t, err, "Unexpected error in testcase: %v", i)
assert.Equal(t, template.HTML(c.Expected), result, "Unexpected result in testcase %v", i)
assert.Equal(t, c.Expected, string(result), "Unexpected result in testcase %v", i)
}
}

Expand Down
29 changes: 2 additions & 27 deletions modules/markup/markdown/transform_link.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,13 @@
package markdown

import (
"path/filepath"

"code.gitea.io/gitea/modules/markup"
giteautil "code.gitea.io/gitea/modules/util"

"github.com/yuin/goldmark/ast"
)

func (g *ASTTransformer) transformLink(ctx *markup.RenderContext, v *ast.Link) {
// Links need their href to munged to be a real value
link := v.Destination
isAnchorFragment := len(link) > 0 && link[0] == '#'
if !isAnchorFragment && !markup.IsFullURLBytes(link) {
base := ctx.Links.Base
if ctx.IsWiki {
if filepath.Ext(string(link)) == "" {
// This link doesn't have a file extension - assume a regular wiki link
base = ctx.Links.WikiLink()
} else if markup.Type(string(link)) != "" {
// If it's a file type we can render, use a regular wiki link
base = ctx.Links.WikiLink()
} else {
// Otherwise, use a raw link instead
base = ctx.Links.WikiRawLink()
}
} else if ctx.Links.HasBranchInfo() {
base = ctx.Links.SrcLink()
}
link = []byte(giteautil.URLJoin(base, string(link)))
}
if isAnchorFragment {
link = []byte("#user-content-" + string(link)[1:])
if link, resolved := markup.ResolveLink(ctx, string(v.Destination), "#user-content-"); resolved {
v.Destination = []byte(link)
}
v.Destination = link
}
12 changes: 2 additions & 10 deletions modules/markup/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,22 +372,14 @@ func renderFile(ctx *RenderContext, input io.Reader, output io.Writer) error {
return ErrUnsupportedRenderExtension{extension}
}

// Type returns if markup format via the filename
func Type(filename string) string {
// DetectMarkupTypeByFileName returns the possible markup format type via the filename
func DetectMarkupTypeByFileName(filename string) string {
if parser := GetRendererByFileName(filename); parser != nil {
return parser.Name()
}
return ""
}

// IsMarkupFile reports whether file is a markup type file
func IsMarkupFile(name, markup string) bool {
if parser := GetRendererByFileName(name); parser != nil {
return parser.Name() == markup
}
return false
}

func PreviewableExtensions() []string {
extensions := make([]string, 0, len(extRenderers))
for extension := range extRenderers {
Expand Down
4 changes: 2 additions & 2 deletions modules/templates/util_render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func TestRenderMarkdownToHtml(t *testing.T) {
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a>
<a href="/file.bin" rel="nofollow">local link</a>
<a href="https://example.com" rel="nofollow">remote link</a>
<a href="/src/file.bin" rel="nofollow">local link</a>
<a href="/file.bin" rel="nofollow">local link</a>
<a href="https://example.com" rel="nofollow">remote link</a>
<a href="/image.jpg" target="_blank" rel="nofollow noopener"><img src="/image.jpg" alt="local image"/></a>
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a>
Expand All @@ -190,7 +190,7 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
#123
space</p>
`
assert.EqualValues(t, expected, RenderMarkdownToHtml(context.Background(), testInput()))
assert.Equal(t, expected, string(RenderMarkdownToHtml(context.Background(), testInput())))
}

func TestRenderLabels(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func RenderFile(ctx *context.Context) {
rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc), charset.ConvertOpts{})
ctx.Resp.Header().Add("Content-Security-Policy", "frame-src 'self'; sandbox allow-scripts")

if markupType := markup.Type(blob.Name()); markupType == "" {
if markupType := markup.DetectMarkupTypeByFileName(blob.Name()); markupType == "" {
if isTextFile {
_, _ = io.Copy(ctx.Resp, rd)
} else {
Expand Down
6 changes: 3 additions & 3 deletions routers/web/repo/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr

rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc), charset.ConvertOpts{})

if markupType := markup.Type(readmeFile.Name()); markupType != "" {
if markupType := markup.DetectMarkupTypeByFileName(readmeFile.Name()); markupType != "" {
ctx.Data["IsMarkup"] = true
ctx.Data["MarkupType"] = markupType

Expand Down Expand Up @@ -499,7 +499,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry) {
readmeExist := util.IsReadmeFileName(blob.Name())
ctx.Data["ReadmeExist"] = readmeExist

markupType := markup.Type(blob.Name())
markupType := markup.DetectMarkupTypeByFileName(blob.Name())
// If the markup is detected by custom markup renderer it should not be reset later on
// to not pass it down to the render context.
detected := false
Expand Down Expand Up @@ -607,7 +607,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry) {

// TODO: this logic duplicates with "isRepresentableAsText=true", it is not the same as "LFSFileGet" in "lfs.go"
// It is used by "external renders", markupRender will execute external programs to get rendered content.
if markupType := markup.Type(blob.Name()); markupType != "" {
if markupType := markup.DetectMarkupTypeByFileName(blob.Name()); markupType != "" {
rd := io.MultiReader(bytes.NewReader(buf), dataRc)
ctx.Data["IsMarkup"] = true
ctx.Data["MarkupType"] = markupType
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/wiki.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ func Wiki(ctx *context.Context) {
}

wikiPath := entry.Name()
if markup.Type(wikiPath) != markdown.MarkupName {
if markup.DetectMarkupTypeByFileName(wikiPath) != markdown.MarkupName {
ext := strings.ToUpper(filepath.Ext(wikiPath))
ctx.Data["FormatWarning"] = fmt.Sprintf("%s rendering is not supported at the moment. Rendered as Markdown.", ext)
}
Expand Down