@@ -6,10 +6,12 @@ package markup
66import  (
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
2224func  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 
5055func  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 
130122type  Writer  struct  {
131123	* org.HTMLWriter 
132- 	Ctx  * markup.RenderContext 
124+ 	rctx  * markup.RenderContext 
133125}
134126
135127func  (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 {
154146func  (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}
0 commit comments