mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 09:44:21 +00:00 
			
		
		
		
	Fix orgmode link resolving (#29024)
Fix #28974 Add some new tests and fix some legacy unclear tests.
This commit is contained in:
		@@ -133,18 +133,18 @@ type Writer struct {
 | 
				
			|||||||
	Ctx *markup.RenderContext
 | 
						Ctx *markup.RenderContext
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const mailto = "mailto:"
 | 
					func (r *Writer) resolveLink(kind, link string) string {
 | 
				
			||||||
 | 
						link = strings.TrimPrefix(link, "file:")
 | 
				
			||||||
func (r *Writer) resolveLink(l org.RegularLink) string {
 | 
						if !strings.HasPrefix(link, "#") && // not a URL fragment
 | 
				
			||||||
	link := html.EscapeString(l.URL)
 | 
							!markup.IsLinkStr(link) && // not an absolute URL
 | 
				
			||||||
	if l.Protocol == "file" {
 | 
							!strings.HasPrefix(link, "mailto:") {
 | 
				
			||||||
		link = link[len("file:"):]
 | 
							if kind == "regular" {
 | 
				
			||||||
	}
 | 
								// orgmode reports the link kind as "regular" for "[[ImageLink.svg][The Image Desc]]"
 | 
				
			||||||
	if len(link) > 0 && !markup.IsLinkStr(link) &&
 | 
								// so we need to try to guess the link kind again here
 | 
				
			||||||
		link[0] != '#' && !strings.HasPrefix(link, mailto) {
 | 
								kind = org.RegularLink{URL: link}.Kind()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		base := r.Ctx.Links.Base
 | 
							base := r.Ctx.Links.Base
 | 
				
			||||||
		switch l.Kind() {
 | 
							if kind == "image" || kind == "video" {
 | 
				
			||||||
		case "image", "video":
 | 
					 | 
				
			||||||
			base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsWiki)
 | 
								base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsWiki)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		link = util.URLJoin(base, link)
 | 
							link = util.URLJoin(base, link)
 | 
				
			||||||
@@ -154,29 +154,29 @@ func (r *Writer) resolveLink(l org.RegularLink) string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// WriteRegularLink renders images, links or videos
 | 
					// WriteRegularLink renders images, links or videos
 | 
				
			||||||
func (r *Writer) WriteRegularLink(l org.RegularLink) {
 | 
					func (r *Writer) WriteRegularLink(l org.RegularLink) {
 | 
				
			||||||
	link := r.resolveLink(l)
 | 
						link := r.resolveLink(l.Kind(), l.URL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Inspired by https://github.com/niklasfasching/go-org/blob/6eb20dbda93cb88c3503f7508dc78cbbc639378f/org/html_writer.go#L406-L427
 | 
						// Inspired by https://github.com/niklasfasching/go-org/blob/6eb20dbda93cb88c3503f7508dc78cbbc639378f/org/html_writer.go#L406-L427
 | 
				
			||||||
	switch l.Kind() {
 | 
						switch l.Kind() {
 | 
				
			||||||
	case "image":
 | 
						case "image":
 | 
				
			||||||
		if l.Description == nil {
 | 
							if l.Description == nil {
 | 
				
			||||||
			fmt.Fprintf(r, `<img src="%s" alt="%s" />`, link, link)
 | 
								_, _ = fmt.Fprintf(r, `<img src="%s" alt="%s" />`, link, link)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			imageSrc := r.resolveLink(l.Description[0].(org.RegularLink))
 | 
								imageSrc := r.resolveLink(l.Kind(), org.String(l.Description...))
 | 
				
			||||||
			fmt.Fprintf(r, `<a href="%s"><img src="%s" alt="%s" /></a>`, link, imageSrc, imageSrc)
 | 
								_, _ = fmt.Fprintf(r, `<a href="%s"><img src="%s" alt="%s" /></a>`, link, imageSrc, imageSrc)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case "video":
 | 
						case "video":
 | 
				
			||||||
		if l.Description == nil {
 | 
							if l.Description == nil {
 | 
				
			||||||
			fmt.Fprintf(r, `<video src="%s">%s</video>`, link, link)
 | 
								_, _ = fmt.Fprintf(r, `<video src="%s">%s</video>`, link, link)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			videoSrc := r.resolveLink(l.Description[0].(org.RegularLink))
 | 
								videoSrc := r.resolveLink(l.Kind(), org.String(l.Description...))
 | 
				
			||||||
			fmt.Fprintf(r, `<a href="%s"><video src="%s">%s</video></a>`, link, videoSrc, videoSrc)
 | 
								_, _ = fmt.Fprintf(r, `<a href="%s"><video src="%s">%s</video></a>`, link, videoSrc, videoSrc)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		description := link
 | 
							description := link
 | 
				
			||||||
		if l.Description != nil {
 | 
							if l.Description != nil {
 | 
				
			||||||
			description = r.WriteNodesAsString(l.Description...)
 | 
								description = r.WriteNodesAsString(l.Description...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Fprintf(r, `<a href="%s">%s</a>`, link, description)
 | 
							_, _ = fmt.Fprintf(r, `<a href="%s">%s</a>`, link, description)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,26 +10,21 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/git"
 | 
						"code.gitea.io/gitea/modules/git"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/markup"
 | 
						"code.gitea.io/gitea/modules/markup"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/util"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const AppURL = "http://localhost:3000/"
 | 
				
			||||||
	AppURL    = "http://localhost:3000/"
 | 
					 | 
				
			||||||
	Repo      = "gogits/gogs"
 | 
					 | 
				
			||||||
	AppSubURL = AppURL + Repo + "/"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRender_StandardLinks(t *testing.T) {
 | 
					func TestRender_StandardLinks(t *testing.T) {
 | 
				
			||||||
	setting.AppURL = AppURL
 | 
						setting.AppURL = AppURL
 | 
				
			||||||
	setting.AppSubURL = AppSubURL
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test := func(input, expected string) {
 | 
						test := func(input, expected string) {
 | 
				
			||||||
		buffer, err := RenderString(&markup.RenderContext{
 | 
							buffer, err := RenderString(&markup.RenderContext{
 | 
				
			||||||
			Ctx: git.DefaultContext,
 | 
								Ctx: git.DefaultContext,
 | 
				
			||||||
			Links: markup.Links{
 | 
								Links: markup.Links{
 | 
				
			||||||
				Base: setting.AppSubURL,
 | 
									Base:       "/relative-path",
 | 
				
			||||||
 | 
									BranchPath: "branch/main",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, input)
 | 
							}, input)
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
@@ -38,32 +33,30 @@ func TestRender_StandardLinks(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	test("[[https://google.com/]]",
 | 
						test("[[https://google.com/]]",
 | 
				
			||||||
		`<p><a href="https://google.com/">https://google.com/</a></p>`)
 | 
							`<p><a href="https://google.com/">https://google.com/</a></p>`)
 | 
				
			||||||
 | 
						test("[[WikiPage][The WikiPage Desc]]",
 | 
				
			||||||
	lnk := util.URLJoin(AppSubURL, "WikiPage")
 | 
							`<p><a href="/relative-path/WikiPage">The WikiPage Desc</a></p>`)
 | 
				
			||||||
	test("[[WikiPage][WikiPage]]",
 | 
						test("[[ImageLink.svg][The Image Desc]]",
 | 
				
			||||||
		`<p><a href="`+lnk+`">WikiPage</a></p>`)
 | 
							`<p><a href="/relative-path/media/branch/main/ImageLink.svg">The Image Desc</a></p>`)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRender_Media(t *testing.T) {
 | 
					func TestRender_Media(t *testing.T) {
 | 
				
			||||||
	setting.AppURL = AppURL
 | 
						setting.AppURL = AppURL
 | 
				
			||||||
	setting.AppSubURL = AppSubURL
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test := func(input, expected string) {
 | 
						test := func(input, expected string) {
 | 
				
			||||||
		buffer, err := RenderString(&markup.RenderContext{
 | 
							buffer, err := RenderString(&markup.RenderContext{
 | 
				
			||||||
			Ctx: git.DefaultContext,
 | 
								Ctx: git.DefaultContext,
 | 
				
			||||||
			Links: markup.Links{
 | 
								Links: markup.Links{
 | 
				
			||||||
				Base: setting.AppSubURL,
 | 
									Base: "./relative-path",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, input)
 | 
							}, input)
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
 | 
							assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	url := "../../.images/src/02/train.jpg"
 | 
						test("[[file:../../.images/src/02/train.jpg]]",
 | 
				
			||||||
	result := util.URLJoin(AppSubURL, url)
 | 
							`<p><img src=".images/src/02/train.jpg" alt=".images/src/02/train.jpg" /></p>`)
 | 
				
			||||||
 | 
						test("[[file:train.jpg]]",
 | 
				
			||||||
	test("[[file:"+url+"]]",
 | 
							`<p><img src="relative-path/train.jpg" alt="relative-path/train.jpg" /></p>`)
 | 
				
			||||||
		`<p><img src="`+result+`" alt="`+result+`" /></p>`)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// With description.
 | 
						// With description.
 | 
				
			||||||
	test("[[https://example.com][https://example.com/example.svg]]",
 | 
						test("[[https://example.com][https://example.com/example.svg]]",
 | 
				
			||||||
@@ -80,11 +73,20 @@ func TestRender_Media(t *testing.T) {
 | 
				
			|||||||
		`<p><img src="https://example.com/example.svg" alt="https://example.com/example.svg" /></p>`)
 | 
							`<p><img src="https://example.com/example.svg" alt="https://example.com/example.svg" /></p>`)
 | 
				
			||||||
	test("[[https://example.com/example.mp4]]",
 | 
						test("[[https://example.com/example.mp4]]",
 | 
				
			||||||
		`<p><video src="https://example.com/example.mp4">https://example.com/example.mp4</video></p>`)
 | 
							`<p><video src="https://example.com/example.mp4">https://example.com/example.mp4</video></p>`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// test [[LINK][DESCRIPTION]] syntax with "file:" prefix
 | 
				
			||||||
 | 
						test(`[[https://example.com/][file:https://example.com/foo%20bar.svg]]`,
 | 
				
			||||||
 | 
							`<p><a href="https://example.com/"><img src="https://example.com/foo%20bar.svg" alt="https://example.com/foo%20bar.svg" /></a></p>`)
 | 
				
			||||||
 | 
						test(`[[file:https://example.com/foo%20bar.svg][Goto Image]]`,
 | 
				
			||||||
 | 
							`<p><a href="https://example.com/foo%20bar.svg">Goto Image</a></p>`)
 | 
				
			||||||
 | 
						test(`[[file:https://example.com/link][https://example.com/image.jpg]]`,
 | 
				
			||||||
 | 
							`<p><a href="https://example.com/link"><img src="https://example.com/image.jpg" alt="https://example.com/image.jpg" /></a></p>`)
 | 
				
			||||||
 | 
						test(`[[file:https://example.com/link][file:https://example.com/image.jpg]]`,
 | 
				
			||||||
 | 
							`<p><a href="https://example.com/link"><img src="https://example.com/image.jpg" alt="https://example.com/image.jpg" /></a></p>`)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRender_Source(t *testing.T) {
 | 
					func TestRender_Source(t *testing.T) {
 | 
				
			||||||
	setting.AppURL = AppURL
 | 
						setting.AppURL = AppURL
 | 
				
			||||||
	setting.AppSubURL = AppSubURL
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test := func(input, expected string) {
 | 
						test := func(input, expected string) {
 | 
				
			||||||
		buffer, err := RenderString(&markup.RenderContext{
 | 
							buffer, err := RenderString(&markup.RenderContext{
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user