@@ -6,10 +6,12 @@ package markup
6
6
import (
7
7
"fmt"
8
8
"html"
9
+ "html/template"
9
10
"io"
10
11
"strings"
11
12
12
13
"code.gitea.io/gitea/modules/highlight"
14
+ "code.gitea.io/gitea/modules/htmlutil"
13
15
"code.gitea.io/gitea/modules/log"
14
16
"code.gitea.io/gitea/modules/markup"
15
17
"code.gitea.io/gitea/modules/setting"
@@ -20,33 +22,36 @@ import (
20
22
)
21
23
22
24
func init () {
23
- markup .RegisterRenderer (Renderer {})
25
+ markup .RegisterRenderer (orgRenderer {})
24
26
}
25
27
26
28
// Renderer implements markup.Renderer for orgmode
27
- type Renderer struct {}
29
+ type orgRenderer struct {}
28
30
29
- var _ markup.PostProcessRenderer = (* Renderer )(nil )
31
+ var (
32
+ _ markup.Renderer = (* orgRenderer )(nil )
33
+ _ markup.PostProcessRenderer = (* orgRenderer )(nil )
34
+ )
30
35
31
36
// Name implements markup.Renderer
32
- func (Renderer ) Name () string {
37
+ func (orgRenderer ) Name () string {
33
38
return "orgmode"
34
39
}
35
40
36
41
// NeedPostProcess implements markup.PostProcessRenderer
37
- func (Renderer ) NeedPostProcess () bool { return true }
42
+ func (orgRenderer ) NeedPostProcess () bool { return true }
38
43
39
44
// Extensions implements markup.Renderer
40
- func (Renderer ) Extensions () []string {
45
+ func (orgRenderer ) Extensions () []string {
41
46
return []string {".org" }
42
47
}
43
48
44
49
// SanitizerRules implements markup.Renderer
45
- func (Renderer ) SanitizerRules () []setting.MarkupSanitizerRule {
50
+ func (orgRenderer ) SanitizerRules () []setting.MarkupSanitizerRule {
46
51
return []setting.MarkupSanitizerRule {}
47
52
}
48
53
49
- // Render renders orgmode rawbytes to HTML
54
+ // Render renders orgmode raw bytes to HTML
50
55
func Render (ctx * markup.RenderContext , input io.Reader , output io.Writer ) error {
51
56
htmlWriter := org .NewHTMLWriter ()
52
57
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
56
61
panic (err )
57
62
}
58
63
}()
59
- var w strings.Builder
60
- if _ , err := w .WriteString (`<pre>` ); err != nil {
61
- return ""
62
- }
64
+ w := & strings.Builder {}
63
65
64
66
lexer := lexers .Get (lang )
65
67
if lexer == nil && lang == "" {
@@ -70,38 +72,28 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
70
72
lang = strings .ToLower (lexer .Config ().Name )
71
73
}
72
74
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
+ }
73
79
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
- }
78
80
if _ , err := w .WriteString (html .EscapeString (source )); err != nil {
79
81
return ""
80
82
}
81
83
} 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
- }
86
84
lexer = chroma .Coalesce (lexer )
87
-
88
85
if _ , err := w .WriteString (string (highlight .CodeFromLexer (lexer , source ))); err != nil {
89
86
return ""
90
87
}
91
88
}
92
-
93
89
if _ , err := w .WriteString ("</code></pre>" ); err != nil {
94
90
return ""
95
91
}
96
92
97
93
return w .String ()
98
94
}
99
95
100
- w := & Writer {
101
- HTMLWriter : htmlWriter ,
102
- Ctx : ctx ,
103
- }
104
-
96
+ w := & Writer {rctx : ctx , HTMLWriter : htmlWriter }
105
97
htmlWriter .ExtendingWriter = w
106
98
107
99
res , err := org .New ().Silent ().Parse (input , "" ).Write (w )
@@ -122,14 +114,14 @@ func RenderString(ctx *markup.RenderContext, content string) (string, error) {
122
114
}
123
115
124
116
// 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 {
126
118
return Render (ctx , input , output )
127
119
}
128
120
129
121
// Writer implements org.Writer
130
122
type Writer struct {
131
123
* org.HTMLWriter
132
- Ctx * markup.RenderContext
124
+ rctx * markup.RenderContext
133
125
}
134
126
135
127
func (r * Writer ) resolveLink (kind , link string ) string {
@@ -142,9 +134,9 @@ func (r *Writer) resolveLink(kind, link string) string {
142
134
kind = org.RegularLink {URL : link }.Kind ()
143
135
}
144
136
if kind == "image" || kind == "video" {
145
- link = r .Ctx .RenderHelper .ResolveLink (link , markup .LinkTypeMedia )
137
+ link = r .rctx .RenderHelper .ResolveLink (link , markup .LinkTypeMedia )
146
138
} else {
147
- link = r .Ctx .RenderHelper .ResolveLink (link , markup .LinkTypeDefault )
139
+ link = r .rctx .RenderHelper .ResolveLink (link , markup .LinkTypeDefault )
148
140
}
149
141
}
150
142
return link
@@ -154,27 +146,30 @@ func (r *Writer) resolveLink(kind, link string) string {
154
146
func (r * Writer ) WriteRegularLink (l org.RegularLink ) {
155
147
link := r .resolveLink (l .Kind (), l .URL )
156
148
149
+ printHTML := func (html string , a ... any ) {
150
+ _ , _ = fmt .Fprint (r , htmlutil .HTMLFormat (html , a ... ))
151
+ }
157
152
// Inspired by https://github.com/niklasfasching/go-org/blob/6eb20dbda93cb88c3503f7508dc78cbbc639378f/org/html_writer.go#L406-L427
158
153
switch l .Kind () {
159
154
case "image" :
160
155
if l .Description == nil {
161
- _ , _ = fmt . Fprintf ( r , `<img src="%s" alt="%s" / >` , link , link )
156
+ printHTML ( `<img src="%s" alt="%s">` , link , link )
162
157
} else {
163
158
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 )
165
160
}
166
161
case "video" :
167
162
if l .Description == nil {
168
- _ , _ = fmt . Fprintf ( r , `<video src="%s">%s</video>` , link , link )
163
+ printHTML ( `<video src="%s">%s</video>` , link , link )
169
164
} else {
170
165
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 )
172
167
}
173
168
default :
174
- description : = link
169
+ var description any = link
175
170
if l .Description != nil {
176
- description = r .WriteNodesAsString (l .Description ... )
171
+ description = template . HTML ( r .WriteNodesAsString (l .Description ... )) // orgmode HTMLWriter outputs HTML content
177
172
}
178
- _ , _ = fmt . Fprintf ( r , `<a href="%s">%s</a>` , link , description )
173
+ printHTML ( `<a href="%s">%s</a>` , link , description )
179
174
}
180
175
}
0 commit comments