Skip to content

Commit 9186844

Browse files
committed
fix
1 parent a1f56f8 commit 9186844

File tree

3 files changed

+80
-46
lines changed

3 files changed

+80
-46
lines changed

Diff for: models/renderhelper/repo_file_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
"code.gitea.io/gitea/modules/markup"
1313
"code.gitea.io/gitea/modules/markup/markdown"
1414

15+
_ "code.gitea.io/gitea/modules/markup/orgmode"
16+
1517
"github.com/stretchr/testify/assert"
1618
)
1719

@@ -81,3 +83,40 @@ func TestRepoFile(t *testing.T) {
8183
</video>`, rendered)
8284
})
8385
}
86+
87+
func TestRepoFileOrgMode(t *testing.T) {
88+
unittest.PrepareTestEnv(t)
89+
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
90+
91+
t.Run("Links", func(t *testing.T) {
92+
rctx := NewRenderContextRepoFile(context.Background(), repo1, RepoFileOptions{
93+
CurrentRefPath: "/commit/1234",
94+
CurrentTreePath: "my-dir",
95+
}).WithRelativePath("my-dir/a.org")
96+
97+
rendered, err := markup.RenderString(rctx, `
98+
[[https://google.com/]]
99+
[[ImageLink.svg][The Image Desc]]
100+
`)
101+
assert.NoError(t, err)
102+
assert.Equal(t, `<p>
103+
<a href="https://google.com/" rel="nofollow">https://google.com/</a>
104+
<a href="/user2/repo1/media/commit/1234/my-dir/ImageLink.svg" rel="nofollow">The Image Desc</a></p>
105+
`, rendered)
106+
})
107+
108+
t.Run("CodeHighlight", func(t *testing.T) {
109+
rctx := NewRenderContextRepoFile(context.Background(), repo1, RepoFileOptions{}).WithRelativePath("my-dir/a.org")
110+
111+
rendered, err := markup.RenderString(rctx, `
112+
#+begin_src c
113+
int a = 1;
114+
#+end_src
115+
`)
116+
assert.NoError(t, err)
117+
assert.Equal(t, `<div>
118+
<pre><code class="chroma language-c"><span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span></code></pre>
119+
</div>
120+
`, rendered)
121+
})
122+
}

Diff for: modules/markup/orgmode/orgmode.go

+33-38
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ package markup
66
import (
77
"fmt"
88
"html"
9+
"html/template"
910
"io"
1011
"strings"
1112

1213
"code.gitea.io/gitea/modules/highlight"
14+
"code.gitea.io/gitea/modules/htmlutil"
1315
"code.gitea.io/gitea/modules/log"
1416
"code.gitea.io/gitea/modules/markup"
1517
"code.gitea.io/gitea/modules/setting"
@@ -20,33 +22,36 @@ import (
2022
)
2123

2224
func init() {
23-
markup.RegisterRenderer(Renderer{})
25+
markup.RegisterRenderer(orgRenderer{})
2426
}
2527

2628
// Renderer implements markup.Renderer for orgmode
27-
type Renderer struct{}
29+
type orgRenderer struct{}
2830

29-
var _ markup.PostProcessRenderer = (*Renderer)(nil)
31+
var (
32+
_ markup.Renderer = (*orgRenderer)(nil)
33+
_ markup.PostProcessRenderer = (*orgRenderer)(nil)
34+
)
3035

3136
// Name implements markup.Renderer
32-
func (Renderer) Name() string {
37+
func (orgRenderer) Name() string {
3338
return "orgmode"
3439
}
3540

3641
// NeedPostProcess implements markup.PostProcessRenderer
37-
func (Renderer) NeedPostProcess() bool { return true }
42+
func (orgRenderer) NeedPostProcess() bool { return true }
3843

3944
// Extensions implements markup.Renderer
40-
func (Renderer) Extensions() []string {
45+
func (orgRenderer) Extensions() []string {
4146
return []string{".org"}
4247
}
4348

4449
// SanitizerRules implements markup.Renderer
45-
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
50+
func (orgRenderer) SanitizerRules() []setting.MarkupSanitizerRule {
4651
return []setting.MarkupSanitizerRule{}
4752
}
4853

49-
// Render renders orgmode rawbytes to HTML
54+
// Render renders orgmode raw bytes to HTML
5055
func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error {
5156
htmlWriter := org.NewHTMLWriter()
5257
htmlWriter.HighlightCodeBlock = func(source, lang string, inline bool, params map[string]string) string {
@@ -56,10 +61,7 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
5661
panic(err)
5762
}
5863
}()
59-
var w strings.Builder
60-
if _, err := w.WriteString(`<pre>`); err != nil {
61-
return ""
62-
}
64+
w := &strings.Builder{}
6365

6466
lexer := lexers.Get(lang)
6567
if lexer == nil && lang == "" {
@@ -70,38 +72,28 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
7072
lang = strings.ToLower(lexer.Config().Name)
7173
}
7274

75+
// include language-x class as part of commonmark spec
76+
if err := ctx.RenderInternal.FormatWithSafeAttrs(w, `<pre><code class="chroma language-%s">`, lang); err != nil {
77+
return ""
78+
}
7379
if lexer == nil {
74-
// include language-x class as part of commonmark spec
75-
if _, err := w.WriteString(`<code class="chroma language-` + lang + `">`); err != nil {
76-
return ""
77-
}
7880
if _, err := w.WriteString(html.EscapeString(source)); err != nil {
7981
return ""
8082
}
8183
} else {
82-
// include language-x class as part of commonmark spec
83-
if _, err := w.WriteString(`<code class="chroma language-` + lang + `">`); err != nil {
84-
return ""
85-
}
8684
lexer = chroma.Coalesce(lexer)
87-
8885
if _, err := w.WriteString(string(highlight.CodeFromLexer(lexer, source))); err != nil {
8986
return ""
9087
}
9188
}
92-
9389
if _, err := w.WriteString("</code></pre>"); err != nil {
9490
return ""
9591
}
9692

9793
return w.String()
9894
}
9995

100-
w := &Writer{
101-
HTMLWriter: htmlWriter,
102-
Ctx: ctx,
103-
}
104-
96+
w := &Writer{rctx: ctx, HTMLWriter: htmlWriter}
10597
htmlWriter.ExtendingWriter = w
10698

10799
res, err := org.New().Silent().Parse(input, "").Write(w)
@@ -122,14 +114,14 @@ func RenderString(ctx *markup.RenderContext, content string) (string, error) {
122114
}
123115

124116
// Render renders orgmode string to HTML string
125-
func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error {
117+
func (orgRenderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error {
126118
return Render(ctx, input, output)
127119
}
128120

129121
// Writer implements org.Writer
130122
type Writer struct {
131123
*org.HTMLWriter
132-
Ctx *markup.RenderContext
124+
rctx *markup.RenderContext
133125
}
134126

135127
func (r *Writer) resolveLink(kind, link string) string {
@@ -142,9 +134,9 @@ func (r *Writer) resolveLink(kind, link string) string {
142134
kind = org.RegularLink{URL: link}.Kind()
143135
}
144136
if kind == "image" || kind == "video" {
145-
link = r.Ctx.RenderHelper.ResolveLink(link, markup.LinkTypeMedia)
137+
link = r.rctx.RenderHelper.ResolveLink(link, markup.LinkTypeMedia)
146138
} else {
147-
link = r.Ctx.RenderHelper.ResolveLink(link, markup.LinkTypeDefault)
139+
link = r.rctx.RenderHelper.ResolveLink(link, markup.LinkTypeDefault)
148140
}
149141
}
150142
return link
@@ -154,27 +146,30 @@ func (r *Writer) resolveLink(kind, link string) string {
154146
func (r *Writer) WriteRegularLink(l org.RegularLink) {
155147
link := r.resolveLink(l.Kind(), l.URL)
156148

149+
printHTML := func(html string, a ...any) {
150+
_, _ = fmt.Fprint(r, htmlutil.HTMLFormat(html, a...))
151+
}
157152
// Inspired by https://github.com/niklasfasching/go-org/blob/6eb20dbda93cb88c3503f7508dc78cbbc639378f/org/html_writer.go#L406-L427
158153
switch l.Kind() {
159154
case "image":
160155
if l.Description == nil {
161-
_, _ = fmt.Fprintf(r, `<img src="%s" alt="%s" />`, link, link)
156+
printHTML(`<img src="%s" alt="%s">`, link, link)
162157
} else {
163158
imageSrc := r.resolveLink(l.Kind(), org.String(l.Description...))
164-
_, _ = fmt.Fprintf(r, `<a href="%s"><img src="%s" alt="%s" /></a>`, link, imageSrc, imageSrc)
159+
printHTML(`<a href="%s"><img src="%s" alt="%s"></a>`, link, imageSrc, imageSrc)
165160
}
166161
case "video":
167162
if l.Description == nil {
168-
_, _ = fmt.Fprintf(r, `<video src="%s">%s</video>`, link, link)
163+
printHTML(`<video src="%s">%s</video>`, link, link)
169164
} else {
170165
videoSrc := r.resolveLink(l.Kind(), org.String(l.Description...))
171-
_, _ = fmt.Fprintf(r, `<a href="%s"><video src="%s">%s</video></a>`, link, videoSrc, videoSrc)
166+
printHTML(`<a href="%s"><video src="%s">%s</video></a>`, link, videoSrc, videoSrc)
172167
}
173168
default:
174-
description := link
169+
var description any = link
175170
if l.Description != nil {
176-
description = r.WriteNodesAsString(l.Description...)
171+
description = template.HTML(r.WriteNodesAsString(l.Description...)) // orgmode HTMLWriter outputs HTML content
177172
}
178-
_, _ = fmt.Fprintf(r, `<a href="%s">%s</a>`, link, description)
173+
printHTML(`<a href="%s">%s</a>`, link, description)
179174
}
180175
}

Diff for: modules/markup/orgmode/orgmode_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -58,35 +58,35 @@ func TestRender_Media(t *testing.T) {
5858
}
5959

6060
test("[[file:../../.images/src/02/train.jpg]]",
61-
`<p><img src=".images/src/02/train.jpg" alt=".images/src/02/train.jpg" /></p>`)
61+
`<p><img src=".images/src/02/train.jpg" alt=".images/src/02/train.jpg"></p>`)
6262
test("[[file:train.jpg]]",
63-
`<p><img src="relative-path/train.jpg" alt="relative-path/train.jpg" /></p>`)
63+
`<p><img src="relative-path/train.jpg" alt="relative-path/train.jpg"></p>`)
6464

6565
// With description.
6666
test("[[https://example.com][https://example.com/example.svg]]",
67-
`<p><a href="https://example.com"><img src="https://example.com/example.svg" alt="https://example.com/example.svg" /></a></p>`)
67+
`<p><a href="https://example.com"><img src="https://example.com/example.svg" alt="https://example.com/example.svg"></a></p>`)
6868
test("[[https://example.com][pre https://example.com/example.svg post]]",
69-
`<p><a href="https://example.com">pre <img src="https://example.com/example.svg" alt="https://example.com/example.svg" /> post</a></p>`)
69+
`<p><a href="https://example.com">pre <img src="https://example.com/example.svg" alt="https://example.com/example.svg"> post</a></p>`)
7070
test("[[https://example.com][https://example.com/example.mp4]]",
7171
`<p><a href="https://example.com"><video src="https://example.com/example.mp4">https://example.com/example.mp4</video></a></p>`)
7272
test("[[https://example.com][pre https://example.com/example.mp4 post]]",
7373
`<p><a href="https://example.com">pre <video src="https://example.com/example.mp4">https://example.com/example.mp4</video> post</a></p>`)
7474

7575
// Without description.
7676
test("[[https://example.com/example.svg]]",
77-
`<p><img src="https://example.com/example.svg" alt="https://example.com/example.svg" /></p>`)
77+
`<p><img src="https://example.com/example.svg" alt="https://example.com/example.svg"></p>`)
7878
test("[[https://example.com/example.mp4]]",
7979
`<p><video src="https://example.com/example.mp4">https://example.com/example.mp4</video></p>`)
8080

8181
// test [[LINK][DESCRIPTION]] syntax with "file:" prefix
8282
test(`[[https://example.com/][file:https://example.com/foo%20bar.svg]]`,
83-
`<p><a href="https://example.com/"><img src="https://example.com/foo%20bar.svg" alt="https://example.com/foo%20bar.svg" /></a></p>`)
83+
`<p><a href="https://example.com/"><img src="https://example.com/foo%20bar.svg" alt="https://example.com/foo%20bar.svg"></a></p>`)
8484
test(`[[file:https://example.com/foo%20bar.svg][Goto Image]]`,
8585
`<p><a href="https://example.com/foo%20bar.svg">Goto Image</a></p>`)
8686
test(`[[file:https://example.com/link][https://example.com/image.jpg]]`,
87-
`<p><a href="https://example.com/link"><img src="https://example.com/image.jpg" alt="https://example.com/image.jpg" /></a></p>`)
87+
`<p><a href="https://example.com/link"><img src="https://example.com/image.jpg" alt="https://example.com/image.jpg"></a></p>`)
8888
test(`[[file:https://example.com/link][file:https://example.com/image.jpg]]`,
89-
`<p><a href="https://example.com/link"><img src="https://example.com/image.jpg" alt="https://example.com/image.jpg" /></a></p>`)
89+
`<p><a href="https://example.com/link"><img src="https://example.com/image.jpg" alt="https://example.com/image.jpg"></a></p>`)
9090
}
9191

9292
func TestRender_Source(t *testing.T) {

0 commit comments

Comments
 (0)