From 2bac85dc3339ecb1cb1418524b2a7966aed9963a Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Wed, 7 Feb 2024 16:32:31 +0800 Subject: [PATCH] Fix orgmode link resolving (#29024) Fix #28974 Add some new tests and fix some legacy unclear tests. --- modules/markup/orgmode/orgmode.go | 38 +++++++++++------------ modules/markup/orgmode/orgmode_test.go | 42 ++++++++++++++------------ 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go index abc641fbe2..ac1cedff6d 100644 --- a/modules/markup/orgmode/orgmode.go +++ b/modules/markup/orgmode/orgmode.go @@ -133,18 +133,18 @@ type Writer struct { Ctx *markup.RenderContext } -const mailto = "mailto:" - -func (r *Writer) resolveLink(l org.RegularLink) string { - link := html.EscapeString(l.URL) - if l.Protocol == "file" { - link = link[len("file:"):] - } - if len(link) > 0 && !markup.IsLinkStr(link) && - link[0] != '#' && !strings.HasPrefix(link, mailto) { +func (r *Writer) resolveLink(kind, link string) string { + link = strings.TrimPrefix(link, "file:") + if !strings.HasPrefix(link, "#") && // not a URL fragment + !markup.IsLinkStr(link) && // not an absolute URL + !strings.HasPrefix(link, "mailto:") { + if kind == "regular" { + // orgmode reports the link kind as "regular" for "[[ImageLink.svg][The Image Desc]]" + // so we need to try to guess the link kind again here + kind = org.RegularLink{URL: link}.Kind() + } base := r.Ctx.Links.Base - switch l.Kind() { - case "image", "video": + if kind == "image" || kind == "video" { base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsWiki) } link = util.URLJoin(base, link) @@ -154,29 +154,29 @@ func (r *Writer) resolveLink(l org.RegularLink) string { // WriteRegularLink renders images, links or videos 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 switch l.Kind() { case "image": if l.Description == nil { - fmt.Fprintf(r, `%s`, link, link) + _, _ = fmt.Fprintf(r, `%s`, link, link) } else { - imageSrc := r.resolveLink(l.Description[0].(org.RegularLink)) - fmt.Fprintf(r, `%s`, link, imageSrc, imageSrc) + imageSrc := r.resolveLink(l.Kind(), org.String(l.Description...)) + _, _ = fmt.Fprintf(r, `%s`, link, imageSrc, imageSrc) } case "video": if l.Description == nil { - fmt.Fprintf(r, ``, link, link) + _, _ = fmt.Fprintf(r, ``, link, link) } else { - videoSrc := r.resolveLink(l.Description[0].(org.RegularLink)) - fmt.Fprintf(r, ``, link, videoSrc, videoSrc) + videoSrc := r.resolveLink(l.Kind(), org.String(l.Description...)) + _, _ = fmt.Fprintf(r, ``, link, videoSrc, videoSrc) } default: description := link if l.Description != nil { description = r.WriteNodesAsString(l.Description...) } - fmt.Fprintf(r, `%s`, link, description) + _, _ = fmt.Fprintf(r, `%s`, link, description) } } diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go index abf5ca8fcf..95f53c9cc9 100644 --- a/modules/markup/orgmode/orgmode_test.go +++ b/modules/markup/orgmode/orgmode_test.go @@ -10,26 +10,21 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/util" "github.com/stretchr/testify/assert" ) -const ( - AppURL = "http://localhost:3000/" - Repo = "gogits/gogs" - AppSubURL = AppURL + Repo + "/" -) +const AppURL = "http://localhost:3000/" func TestRender_StandardLinks(t *testing.T) { setting.AppURL = AppURL - setting.AppSubURL = AppSubURL test := func(input, expected string) { buffer, err := RenderString(&markup.RenderContext{ Ctx: git.DefaultContext, Links: markup.Links{ - Base: setting.AppSubURL, + Base: "/relative-path", + BranchPath: "branch/main", }, }, input) assert.NoError(t, err) @@ -38,32 +33,30 @@ func TestRender_StandardLinks(t *testing.T) { test("[[https://google.com/]]", `

https://google.com/

`) - - lnk := util.URLJoin(AppSubURL, "WikiPage") - test("[[WikiPage][WikiPage]]", - `

WikiPage

`) + test("[[WikiPage][The WikiPage Desc]]", + `

The WikiPage Desc

`) + test("[[ImageLink.svg][The Image Desc]]", + `

The Image Desc

`) } func TestRender_Media(t *testing.T) { setting.AppURL = AppURL - setting.AppSubURL = AppSubURL test := func(input, expected string) { buffer, err := RenderString(&markup.RenderContext{ Ctx: git.DefaultContext, Links: markup.Links{ - Base: setting.AppSubURL, + Base: "./relative-path", }, }, input) assert.NoError(t, err) assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) } - url := "../../.images/src/02/train.jpg" - result := util.URLJoin(AppSubURL, url) - - test("[[file:"+url+"]]", - `

`+result+`

`) + test("[[file:../../.images/src/02/train.jpg]]", + `

.images/src/02/train.jpg

`) + test("[[file:train.jpg]]", + `

relative-path/train.jpg

`) // With description. test("[[https://example.com][https://example.com/example.svg]]", @@ -80,11 +73,20 @@ func TestRender_Media(t *testing.T) { `

https://example.com/example.svg

`) test("[[https://example.com/example.mp4]]", `

`) + + // test [[LINK][DESCRIPTION]] syntax with "file:" prefix + test(`[[https://example.com/][file:https://example.com/foo%20bar.svg]]`, + `

https://example.com/foo%20bar.svg

`) + test(`[[file:https://example.com/foo%20bar.svg][Goto Image]]`, + `

Goto Image

`) + test(`[[file:https://example.com/link][https://example.com/image.jpg]]`, + `

https://example.com/image.jpg

`) + test(`[[file:https://example.com/link][file:https://example.com/image.jpg]]`, + `

https://example.com/image.jpg

`) } func TestRender_Source(t *testing.T) { setting.AppURL = AppURL - setting.AppSubURL = AppSubURL test := func(input, expected string) { buffer, err := RenderString(&markup.RenderContext{