Refactor HTMLFormat, update chroma render, fix js error (#33136)
A small refactor to improve HTMLFormat, to help to prevent low-level mistakes. And fix #33141, fix #33139
This commit is contained in:
parent
67aeb1f896
commit
386c1ed908
12 changed files with 34 additions and 17 deletions
|
@ -30,7 +30,7 @@ func ParseSizeAndClass(defaultSize int, defaultClass string, others ...any) (int
|
|||
return size, class
|
||||
}
|
||||
|
||||
func HTMLFormat(s string, rawArgs ...any) template.HTML {
|
||||
func HTMLFormat(s template.HTML, rawArgs ...any) template.HTML {
|
||||
args := slices.Clone(rawArgs)
|
||||
for i, v := range args {
|
||||
switch v := v.(type) {
|
||||
|
@ -44,5 +44,5 @@ func HTMLFormat(s string, rawArgs ...any) template.HTML {
|
|||
args[i] = template.HTMLEscapeString(fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
return template.HTML(fmt.Sprintf(s, args...))
|
||||
return template.HTML(fmt.Sprintf(string(s), args...))
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ func (r *RenderInternal) ProtectSafeAttrs(content template.HTML) template.HTML {
|
|||
return template.HTML(reAttrClass().ReplaceAllString(string(content), `$1 data-attr-class="`+r.secureIDPrefix+`$2"$3`))
|
||||
}
|
||||
|
||||
func (r *RenderInternal) FormatWithSafeAttrs(w io.Writer, fmt string, a ...any) error {
|
||||
func (r *RenderInternal) FormatWithSafeAttrs(w io.Writer, fmt template.HTML, a ...any) error {
|
||||
_, err := w.Write([]byte(r.ProtectSafeAttrs(htmlutil.HTMLFormat(fmt, a...))))
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
package math
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
|
||||
"code.gitea.io/gitea/modules/markup/internal"
|
||||
giteaUtil "code.gitea.io/gitea/modules/util"
|
||||
|
||||
|
@ -50,7 +52,7 @@ func (r *BlockRenderer) renderBlock(w util.BufWriter, source []byte, node gast.N
|
|||
n := node.(*Block)
|
||||
if entering {
|
||||
code := giteaUtil.Iif(n.Inline, "", `<pre class="code-block is-loading">`) + `<code class="language-math display">`
|
||||
_ = r.renderInternal.FormatWithSafeAttrs(w, code)
|
||||
_ = r.renderInternal.FormatWithSafeAttrs(w, template.HTML(code))
|
||||
r.writeLines(w, source, n)
|
||||
} else {
|
||||
_, _ = w.WriteString(`</code>` + giteaUtil.Iif(n.Inline, "", `</pre>`) + "\n")
|
||||
|
|
|
@ -147,7 +147,7 @@ func (r *orgWriter) resolveLink(kind, link string) string {
|
|||
func (r *orgWriter) WriteRegularLink(l org.RegularLink) {
|
||||
link := r.resolveLink(l.Kind(), l.URL)
|
||||
|
||||
printHTML := func(html string, a ...any) {
|
||||
printHTML := func(html template.HTML, a ...any) {
|
||||
_, _ = fmt.Fprint(r, htmlutil.HTMLFormat(html, a...))
|
||||
}
|
||||
// Inspired by https://github.com/niklasfasching/go-org/blob/6eb20dbda93cb88c3503f7508dc78cbbc639378f/org/html_writer.go#L406-L427
|
||||
|
|
|
@ -103,8 +103,8 @@ func HelloWorld() {
|
|||
}
|
||||
#+end_src
|
||||
`, `<div class="src src-go">
|
||||
<pre><code class="chroma language-go"><span class="c1">// HelloWorld prints "Hello World"
|
||||
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">HelloWorld</span><span class="p">()</span> <span class="p">{</span>
|
||||
<pre><code class="chroma language-go"><span class="c1">// HelloWorld prints "Hello World"</span>
|
||||
<span class="kd">func</span> <span class="nf">HelloWorld</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"Hello World"</span><span class="p">)</span>
|
||||
<span class="p">}</span></code></pre>
|
||||
</div>`)
|
||||
|
|
|
@ -38,7 +38,7 @@ func NewFuncMap() template.FuncMap {
|
|||
"Iif": iif,
|
||||
"Eval": evalTokens,
|
||||
"SafeHTML": safeHTML,
|
||||
"HTMLFormat": htmlutil.HTMLFormat,
|
||||
"HTMLFormat": htmlFormat,
|
||||
"HTMLEscape": htmlEscape,
|
||||
"QueryEscape": queryEscape,
|
||||
"QueryBuild": QueryBuild,
|
||||
|
@ -207,6 +207,20 @@ func htmlEscape(s any) template.HTML {
|
|||
panic(fmt.Sprintf("unexpected type %T", s))
|
||||
}
|
||||
|
||||
func htmlFormat(s any, args ...any) template.HTML {
|
||||
if len(args) == 0 {
|
||||
// to prevent developers from calling "HTMLFormat $userInput" by mistake which will lead to XSS
|
||||
panic("missing arguments for HTMLFormat")
|
||||
}
|
||||
switch v := s.(type) {
|
||||
case string:
|
||||
return htmlutil.HTMLFormat(template.HTML(v), args...)
|
||||
case template.HTML:
|
||||
return htmlutil.HTMLFormat(v, args...)
|
||||
}
|
||||
panic(fmt.Sprintf("unexpected type %T", s))
|
||||
}
|
||||
|
||||
func jsEscapeSafe(s string) template.HTML {
|
||||
return template.HTML(template.JSEscapeString(s))
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/htmlutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -88,7 +87,7 @@ func TestTemplateIif(t *testing.T) {
|
|||
func TestTemplateEscape(t *testing.T) {
|
||||
execTmpl := func(code string) string {
|
||||
tmpl := template.New("test")
|
||||
tmpl.Funcs(template.FuncMap{"QueryBuild": QueryBuild, "HTMLFormat": htmlutil.HTMLFormat})
|
||||
tmpl.Funcs(template.FuncMap{"QueryBuild": QueryBuild, "HTMLFormat": htmlFormat})
|
||||
template.Must(tmpl.Parse(code))
|
||||
w := &strings.Builder{}
|
||||
assert.NoError(t, tmpl.Execute(w, nil))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue