mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-11 09:06:19 +00:00
refactor: render highlight language (#38793)
Avoid CSS injection More details are in the comment of CodeBlockAttributes
This commit is contained in:
@@ -7,6 +7,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"gitea.dev/modules/container"
|
||||
"gitea.dev/modules/highlight"
|
||||
"gitea.dev/modules/htmlutil"
|
||||
"gitea.dev/modules/markup"
|
||||
"gitea.dev/modules/markup/internal"
|
||||
|
||||
@@ -129,7 +131,8 @@ func (r *HTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
||||
// renderCodeBlock wraps indented code blocks like the fenced renderer
|
||||
func (r *HTMLRenderer) renderCodeBlock(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||
if entering {
|
||||
opening := r.renderInternal.ProtectSafeAttrs(`<div class="code-block-container code-overflow-scroll"><pre class="code-block"><code>`)
|
||||
preAttrs, codeAttrs := highlight.CodeBlockAttributes("") // no language
|
||||
opening := r.renderInternal.ProtectSafeAttrs(htmlutil.HTMLFormat(`<div class="code-block-container code-overflow-scroll"><pre %s><code %s>`, preAttrs, codeAttrs))
|
||||
if _, err := w.WriteString(string(opening)); err != nil {
|
||||
return ast.WalkStop, err
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/highlight"
|
||||
"gitea.dev/modules/htmlutil"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/markup"
|
||||
@@ -78,17 +79,8 @@ func (r *GoldmarkRender) Convert(source []byte, writer io.Writer, opts ...parser
|
||||
func (r *GoldmarkRender) highlightingRenderer(w util.BufWriter, c highlighting.CodeBlockContext, entering bool) {
|
||||
if entering {
|
||||
languageBytes, _ := c.Language()
|
||||
languageStr := giteautil.IfZero(string(languageBytes), "text")
|
||||
|
||||
preClasses := "code-block"
|
||||
if languageStr == "mermaid" || languageStr == "math" {
|
||||
preClasses += " is-loading"
|
||||
}
|
||||
|
||||
// include language-x class as part of commonmark spec, "chroma" class is used to highlight the code
|
||||
// the "display" class is used by "js/markup/math.ts" to render the code element as a block
|
||||
// the "math.ts" strictly depends on the structure: <pre class="code-block is-loading"><code class="language-math display">...</code></pre>
|
||||
err := r.ctx.RenderInternal.FormatWithSafeAttrs(w, `<div class="code-block-container code-overflow-scroll"><pre class="%s"><code class="chroma language-%s display">`, preClasses, languageStr)
|
||||
preAttrs, codeAttrs := highlight.CodeBlockAttributes(string(languageBytes))
|
||||
err := r.ctx.RenderInternal.FormatWithSafeAttrs(w, `<div class="code-block-container code-overflow-scroll"><pre %s><code %s>`, preAttrs, codeAttrs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ func TestMathRenderBlockIndent(t *testing.T) {
|
||||
\alpha
|
||||
\]
|
||||
`,
|
||||
`<pre class="code-block is-loading"><code class="language-math display">
|
||||
`<pre class="code-block is-loading"><code class="language-math">
|
||||
\alpha
|
||||
</code></pre>
|
||||
`,
|
||||
@@ -147,7 +147,7 @@ func TestMathRenderBlockIndent(t *testing.T) {
|
||||
\alpha
|
||||
\]
|
||||
`,
|
||||
`<pre class="code-block is-loading"><code class="language-math display">
|
||||
`<pre class="code-block is-loading"><code class="language-math">
|
||||
\alpha
|
||||
</code></pre>
|
||||
`,
|
||||
@@ -162,7 +162,7 @@ a
|
||||
d
|
||||
\]
|
||||
`,
|
||||
`<pre class="code-block is-loading"><code class="language-math display">
|
||||
`<pre class="code-block is-loading"><code class="language-math">
|
||||
a
|
||||
b
|
||||
c
|
||||
@@ -179,7 +179,7 @@ c
|
||||
c
|
||||
\]
|
||||
`,
|
||||
`<pre class="code-block is-loading"><code class="language-math display">
|
||||
`<pre class="code-block is-loading"><code class="language-math">
|
||||
a
|
||||
b
|
||||
c
|
||||
@@ -190,7 +190,7 @@ c
|
||||
"indent-0-oneline",
|
||||
`$$ x $$
|
||||
foo`,
|
||||
`<code class="language-math display"> x </code>
|
||||
`<code class="language-math"> x </code>
|
||||
<p>foo</p>
|
||||
`,
|
||||
},
|
||||
@@ -198,7 +198,7 @@ foo`,
|
||||
"indent-3-oneline",
|
||||
` $$ x $$<SPACE>
|
||||
foo`,
|
||||
`<code class="language-math display"> x </code>
|
||||
`<code class="language-math"> x </code>
|
||||
<p>foo</p>
|
||||
`,
|
||||
},
|
||||
@@ -213,10 +213,10 @@ foo`,
|
||||
> \]
|
||||
`,
|
||||
`<blockquote>
|
||||
<pre class="code-block is-loading"><code class="language-math display">
|
||||
<pre class="code-block is-loading"><code class="language-math">
|
||||
a
|
||||
</code></pre>
|
||||
<pre class="code-block is-loading"><code class="language-math display">
|
||||
<pre class="code-block is-loading"><code class="language-math">
|
||||
b
|
||||
</code></pre>
|
||||
</blockquote>
|
||||
@@ -232,7 +232,7 @@ b
|
||||
2. b`,
|
||||
`<ol>
|
||||
<li>a
|
||||
<pre class="code-block is-loading"><code class="language-math display">
|
||||
<pre class="code-block is-loading"><code class="language-math">
|
||||
x
|
||||
</code></pre>
|
||||
</li>
|
||||
@@ -288,7 +288,7 @@ a
|
||||
$$
|
||||
`)
|
||||
setting.Markdown.MathCodeBlockOptions.ParseBlockDollar = true
|
||||
test(t, `<pre class="code-block is-loading"><code class="language-math display">
|
||||
test(t, `<pre class="code-block is-loading"><code class="language-math">
|
||||
a
|
||||
</code></pre>
|
||||
`, `
|
||||
@@ -307,7 +307,7 @@ a
|
||||
\]
|
||||
`)
|
||||
setting.Markdown.MathCodeBlockOptions.ParseBlockSquareBrackets = true
|
||||
test(t, `<pre class="code-block is-loading"><code class="language-math display">
|
||||
test(t, `<pre class="code-block is-loading"><code class="language-math">
|
||||
a
|
||||
</code></pre>
|
||||
`, `
|
||||
|
||||
@@ -611,13 +611,12 @@ func TestMarkdownCodeBlock(t *testing.T) {
|
||||
const prefix = `<div class="code-block-container code-overflow-scroll"><pre class="code-block">`
|
||||
const suffix = `</pre></div>`
|
||||
|
||||
testRender("```\ncode\n```", prefix+`<code class="chroma language-text display">code`+nl+`</code>`+suffix)
|
||||
testRender("```\ncode\n```", prefix+`<code class="chroma language-text">code`+nl+`</code>`+suffix)
|
||||
|
||||
const jsCommon = prefix + `<code class="chroma language-js display"><span class="nx">code</span>` + nl + `</code>` + suffix
|
||||
const jsCommon = prefix + `<code class="chroma language-js"><span class="nx">code</span>` + nl + `</code>` + suffix
|
||||
testRender("```js\ncode\n```", jsCommon)
|
||||
testRender("```js:app.ts\ncode\n```", jsCommon)
|
||||
testRender("```js,ignore\ncode\n```", jsCommon)
|
||||
testRender("```js ignore\ncode\n```", jsCommon)
|
||||
testRender(" code\n", prefix+`<code>code`+nl+`</code>`+suffix)
|
||||
testRender(" <script>alert(1)</script>\n", prefix+`<code><script>alert(1)</script>`+nl+`</code>`+suffix)
|
||||
testRender(" <any&content>\n", prefix+`<code class="chroma language-text"><any&content>`+nl+`</code>`+suffix)
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ import (
|
||||
)
|
||||
|
||||
// Block render output:
|
||||
// <pre class="code-block is-loading"><code class="language-math display">...</code></pre>
|
||||
// <pre class="code-block is-loading"><code class="language-math">...</code></pre>
|
||||
//
|
||||
// Keep in mind that there is another "code block" render in "func (r *GlodmarkRender) highlightingRenderer"
|
||||
// Keep in mind that there is another "code block" render in "func (r *GoldmarkRender) highlightingRenderer"
|
||||
// "highlightingRenderer" outputs the math block with extra "chroma" class:
|
||||
// <pre class="code-block is-loading"><code class="chroma language-math display">...</code></pre>
|
||||
// <pre class="code-block is-loading"><code class="chroma language-math">...</code></pre>
|
||||
//
|
||||
// Special classes:
|
||||
// * "is-loading": show a loading indicator
|
||||
@@ -51,7 +51,7 @@ func (r *BlockRenderer) writeLines(w util.BufWriter, source []byte, n gast.Node)
|
||||
func (r *BlockRenderer) renderBlock(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
|
||||
n := node.(*Block)
|
||||
if entering {
|
||||
codeHTML := giteaUtil.Iif[template.HTML](n.Inline, "", `<pre class="code-block is-loading">`) + `<code class="language-math display">`
|
||||
codeHTML := giteaUtil.Iif[template.HTML](n.Inline, "", `<pre class="code-block is-loading">`) + `<code class="language-math">`
|
||||
_, _ = w.WriteString(string(r.renderInternal.ProtectSafeAttrs(codeHTML)))
|
||||
r.writeLines(w, source, n)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user