From 5c723ee0fd8954e11ebef8b2868745ee1e98e7f7 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 3 Nov 2026 12:25:31 +0000 Subject: [PATCH] refactor(markdown): remove `goldmark-highlighting` (#39751) Render fenced code blocks with Gitea's own code block renderer instead of `goldmark-highlighting`, using the managed lexer lookup from `modules/highlight`. Indented and fenced blocks now share one rendering path. Rendered output is unchanged. The trailing newline is stripped on copy in the frontend since https://github.com/go-gitea/gitea/pull/39755. --------- Co-authored-by: wxiaoguang --- assets/go-licenses.json | 5 -- go.mod | 1 - go.sum | 8 --- modules/highlight/highlight.go | 15 ++++- modules/highlight/lexerdetect.go | 8 +-- modules/markup/internal/renderinternal.go | 2 +- modules/markup/markdown/goldmark.go | 23 ++++--- modules/markup/markdown/markdown.go | 61 ++++--------------- .../markup/markdown/math/block_renderer.go | 4 +- modules/markup/markdown/transform_codespan.go | 2 +- modules/markup/orgmode/orgmode.go | 5 +- 11 files changed, 49 insertions(+), 85 deletions(-) diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 622d67abf91..892cc89726b 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -964,11 +964,6 @@ "path": "github.com/yohcop/openid-go/LICENSE", "licenseText": "Copyright 2015 Yohann Coppel\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n" }, - { - "name": "github.com/yuin/goldmark-highlighting/v2", - "path": "github.com/yuin/goldmark-highlighting/v2/LICENSE", - "licenseText": "MIT License\n\nCopyright (c) 2019 Yusuke Inuzuka\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" - }, { "name": "github.com/yuin/goldmark", "path": "github.com/yuin/goldmark/LICENSE", diff --git a/go.mod b/go.mod index f75592cde38..12c1a4768a0 100644 --- a/go.mod +++ b/go.mod @@ -84,7 +84,6 @@ require ( github.com/wneessen/go-mail v0.8.1 github.com/yohcop/openid-go v1.0.1 github.com/yuin/goldmark v1.8.6 - github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc gitlab.com/gitlab-org/api/client-go/v3 v3.39.1 go.yaml.in/yaml/v4 v4.0.0-rc.6.0.20261013184558-04dd63131525 golang.org/x/crypto v0.58.0 diff --git a/go.sum b/go.sum index 7ce50341d97..09192f66830 100644 --- a/go.sum +++ b/go.sum @@ -48,10 +48,8 @@ github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.10.0 h1:LvK7+C6qgz8BPnmn7x github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.10.0/go.mod h1:I28hc9eaiqKCoOB+9Wh/P1IOScfm0xCgyWC6DAo0lmo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= github.com/alecthomas/chroma/v2 v2.27.0 h1:FodwmyOBgJULFYmDqibcp9pvfDLWdtPRh9v/r5BXYZs= github.com/alecthomas/chroma/v2 v2.27.0/go.mod h1:NjJ3ciIgrqBNeIkWZ4e46nseoLDslxU1LmfCoL+wcY8= -github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI= @@ -162,8 +160,6 @@ github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454Wv github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2/v2 v2.11.0 h1:z5uRPHav+eTVpoffDSuUP2KPS4f1ONZaPDK73S8HA0w= @@ -528,7 +524,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -559,11 +554,8 @@ github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3j github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.8.6 h1:d0VcaP1sx9GkFVkoW+KtggpGi2KZ965i14b0+bDQST4= github.com/yuin/goldmark v1.8.6/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= -github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= diff --git a/modules/highlight/highlight.go b/modules/highlight/highlight.go index a93fe1859d4..177ca8e3451 100644 --- a/modules/highlight/highlight.go +++ b/modules/highlight/highlight.go @@ -18,6 +18,7 @@ import ( "github.com/alecthomas/chroma/v2" chromahtml "github.com/alecthomas/chroma/v2/formatters/html" + "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" ) @@ -82,6 +83,13 @@ func htmlEscape(code string) template.HTML { return template.HTML(gohtml.EscapeString(code)) } +func normalizeLexer(lexer chroma.Lexer) chroma.Lexer { + if lexer != lexers.Fallback { + lexer = chroma.Coalesce(lexer) + } + return lexer +} + // RenderCodeSlowGuess tries to get a lexer by file name and language first, // if not found, it will try to guess the lexer by code content, which is slow (more than several hundreds of milliseconds). func RenderCodeSlowGuess(fileName, language, code string) (output template.HTML, lexer chroma.Lexer, lexerDisplayName string) { @@ -96,11 +104,15 @@ func RenderCodeSlowGuess(fileName, language, code string) (output template.HTML, } lexer = detectChromaLexerWithAnalyze(fileName, language, util.UnsafeStringToBytes(code)) // it is also slow + lexer = normalizeLexer(lexer) return RenderCodeByLexer(lexer, code), lexer, formatLexerName(lexer.Config().Name) } -// RenderCodeByLexer returns a HTML version of code string with chroma syntax highlighting classes +// RenderCodeByLexer returns an HTML version of code string with chroma syntax highlighting classes func RenderCodeByLexer(lexer chroma.Lexer, code string) template.HTML { + if lexer == lexers.Fallback { + return htmlEscape(code) // chroma is 3x slower for plain text + } formatter := chromahtml.New(chromahtml.WithClasses(true), chromahtml.WithLineNumbers(false), chromahtml.PreventSurroundingPre(true), @@ -128,6 +140,7 @@ func RenderFullFile(fileName, language string, code []byte) ([]template.HTML, st return renderPlainText(code), formatLexerName(LanguagePlaintext) } lexer := detectChromaLexerWithAnalyze(fileName, language, code) + lexer = normalizeLexer(lexer) lexerName := formatLexerName(lexer.Config().Name) rendered := RenderCodeByLexer(lexer, util.UnsafeBytesToString(code)) unsafeLines := UnsafeSplitHighlightedLines(rendered) diff --git a/modules/highlight/lexerdetect.go b/modules/highlight/lexerdetect.go index 755c4d10766..af0f8936704 100644 --- a/modules/highlight/lexerdetect.go +++ b/modules/highlight/lexerdetect.go @@ -215,7 +215,7 @@ func normalizeFileNameLang(fileName, fileLang string) (string, string) { func DetectChromaLexerByFileName(fileName, fileLang string) chroma.Lexer { lexer, _ := detectChromaLexerByFileName(fileName, fileLang) - return lexer + return normalizeLexer(lexer) } func detectChromaLexerByFileName(fileName, fileLang string) (_ chroma.Lexer, byLang bool) { @@ -289,14 +289,14 @@ func detectChromaLexerWithAnalyze(fileName, lang string, code []byte) chroma.Lex // if lang is provided, and it matches a lexer, use it directly if byLang { - return chroma.Coalesce(lexer) + return lexer } // if a lexer is detected and there is no conflict for the file extension, use it directly fileExt := path.Ext(fileName) _, hasConflicts := chromaLexers().conflictingExtLangMap[fileExt] if !hasConflicts && lexer != lexers.Fallback { - return chroma.Coalesce(lexer) + return lexer } // try to detect language by content, for best guessing for the language @@ -308,5 +308,5 @@ func detectChromaLexerWithAnalyze(fileName, lang string, code []byte) chroma.Lex log.Warn("No chroma lexer found for enry detected language: %s (file: %s), need to fix the language mapping between enry and chroma.", analyzedLanguage, fileName) } } - return chroma.Coalesce(lexer) + return lexer } diff --git a/modules/markup/internal/renderinternal.go b/modules/markup/internal/renderinternal.go index bf33b01f3db..780fa759f1a 100644 --- a/modules/markup/internal/renderinternal.go +++ b/modules/markup/internal/renderinternal.go @@ -70,7 +70,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 template.HTML, a ...any) error { +func (r *RenderInternal) FormatWithSafeAttrsf(w io.Writer, fmt template.HTML, a ...any) error { htmlStr := r.ProtectSafeAttrs(htmlutil.HTMLFormat(fmt, a...)) _, err := io.WriteString(w, string(htmlStr)) return err diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 2d2daa6cc1d..69bfc7f67f0 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -8,7 +8,6 @@ import ( "gitea.dev/modules/container" "gitea.dev/modules/highlight" - "gitea.dev/modules/htmlutil" "gitea.dev/modules/markup" "gitea.dev/modules/markup/internal" "gitea.dev/modules/markup/markdown/math" @@ -145,23 +144,29 @@ func (r *HTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) { reg.Register(KindSummary, r.renderSummary) reg.Register(ast.KindCodeSpan, r.renderCodeSpan) reg.Register(ast.KindCodeBlock, r.renderCodeBlock) + reg.Register(ast.KindFencedCodeBlock, r.renderCodeBlock) reg.Register(KindAttention, r.renderAttention) reg.Register(east.KindTaskCheckBox, r.renderTaskCheckBox) reg.Register(KindRawHTML, r.renderRawHTML) } -// 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 { - preAttrs, codeAttrs := highlight.CodeBlockAttributes("") // no language - opening := r.renderInternal.ProtectSafeAttrs(htmlutil.HTMLFormat(`
`, preAttrs, codeAttrs))
-		if _, err := w.WriteString(string(opening)); err != nil {
+		var language string
+		if fenced, ok := n.(*ast.FencedCodeBlock); ok {
+			language = string(fenced.Language(source))
+		}
+		preAttrs, codeAttrs := highlight.CodeBlockAttributes(language)
+		err := r.renderInternal.FormatWithSafeAttrsf(w, `
`, preAttrs, codeAttrs)
+		if err != nil {
 			return ast.WalkStop, err
 		}
-		lines := n.Lines()
-		for i := 0; i < lines.Len(); i++ {
-			line := lines.At(i)
-			r.Writer.RawWrite(w, line.Value(source))
+
+		code := n.Lines().Value(source)
+		lexer := highlight.DetectChromaLexerByFileName("", language)
+		renderedHTML := highlight.RenderCodeByLexer(lexer, string(code))
+		if _, err = w.WriteString(string(renderedHTML)); err != nil {
+			return ast.WalkStop, err
 		}
 	} else {
 		if _, err := w.WriteString("
"); err != nil { diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go index 015e315995a..3fc3893d5bd 100644 --- a/modules/markup/markdown/markdown.go +++ b/modules/markup/markdown/markdown.go @@ -13,7 +13,6 @@ import ( "slices" "strings" - "gitea.dev/modules/highlight" "gitea.dev/modules/htmlutil" "gitea.dev/modules/log" "gitea.dev/modules/markup" @@ -22,9 +21,7 @@ import ( "gitea.dev/modules/setting" giteautil "gitea.dev/modules/util" - chromahtml "github.com/alecthomas/chroma/v2/formatters/html" "github.com/yuin/goldmark" - highlighting "github.com/yuin/goldmark-highlighting/v2" "github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" @@ -68,32 +65,6 @@ func newParserContext(ctx *markup.RenderContext) parser.Context { return pc } -type GoldmarkRender struct { - ctx *markup.RenderContext - - goldmarkMarkdown goldmark.Markdown -} - -func (r *GoldmarkRender) Convert(source []byte, writer io.Writer, opts ...parser.ParseOption) error { - return r.goldmarkMarkdown.Convert(source, writer, opts...) -} - -func (r *GoldmarkRender) highlightingRenderer(w util.BufWriter, c highlighting.CodeBlockContext, entering bool) { - if entering { - languageBytes, _ := c.Language() - preAttrs, codeAttrs := highlight.CodeBlockAttributes(string(languageBytes)) - err := r.ctx.RenderInternal.FormatWithSafeAttrs(w, `
`, preAttrs, codeAttrs)
-		if err != nil {
-			return
-		}
-	} else {
-		_, err := w.WriteString("
") - if err != nil { - return - } - } -} - type goldmarkEmphasisParser struct { parser.InlineParser } @@ -130,11 +101,10 @@ func goldmarkDefaultParser() parser.Parser { } // SpecializedMarkdown sets up the Gitea specific markdown extensions -func SpecializedMarkdown(ctx *markup.RenderContext) *GoldmarkRender { +func SpecializedMarkdown(ctx *markup.RenderContext) goldmark.Markdown { // TODO: it could use a pool to cache the renderers to reuse them with different contexts // at the moment it is fast enough (see the benchmarks) - r := &GoldmarkRender{ctx: ctx} - r.goldmarkMarkdown = goldmark.New( + return goldmark.New( goldmark.WithParser(goldmarkDefaultParser()), goldmark.WithExtensions( extension.NewTable(extension.WithTableCellAlignMethod(extension.TableCellAlignAttribute)), @@ -142,13 +112,6 @@ func SpecializedMarkdown(ctx *markup.RenderContext) *GoldmarkRender { extension.TaskList, extension.DefinitionList, common.FootnoteExtension, - highlighting.NewHighlighting( - highlighting.WithFormatOptions( - chromahtml.WithClasses(true), - chromahtml.PreventSurroundingPre(true), - ), - highlighting.WithWrapperRenderer(r.highlightingRenderer), - ), math.NewExtension(&ctx.RenderInternal, math.Options{ Enabled: setting.Markdown.EnableMath, ParseInlineDollar: setting.Markdown.MathCodeBlockOptions.ParseInlineDollar, @@ -161,15 +124,11 @@ func SpecializedMarkdown(ctx *markup.RenderContext) *GoldmarkRender { parser.WithAttribute(), parser.WithASTTransformers(util.Prioritized(NewASTTransformer(&ctx.RenderInternal), 10000)), ), - goldmark.WithRendererOptions(html.WithUnsafe()), + goldmark.WithRendererOptions( + html.WithUnsafe(), + renderer.WithNodeRenderers(util.Prioritized(NewHTMLRenderer(&ctx.RenderInternal), 10)), + ), ) - - // Override the original Tasklist renderer! - r.goldmarkMarkdown.Renderer().AddOptions( - renderer.WithNodeRenderers(util.Prioritized(NewHTMLRenderer(&ctx.RenderInternal), 10)), - ) - - return r } // render calls goldmark render to convert Markdown to HTML @@ -275,14 +234,18 @@ func FeedExcerpt(ctx context.Context, content string) string { pc := newParserContext(rctx) pc.Set(renderConfigKey, &RenderConfig{}) start, texts := len(content), []text.Segment(nil) - _ = ast.Walk(SpecializedMarkdown(rctx).goldmarkMarkdown.Parser().Parse(text.NewReader([]byte(content)), parser.WithContext(pc)), func(node ast.Node, entering bool) (ast.WalkStatus, error) { + + mdParser := SpecializedMarkdown(rctx).Parser() + mdReader := text.NewReader([]byte(content)) + mdWalker := func(node ast.Node, entering bool) (ast.WalkStatus, error) { if entering && node.Type() == ast.TypeBlock && node.Lines().Len() > 0 { start = min(start, strings.LastIndexByte(content[:node.Lines().At(0).Start], '\n')+1) } else if textNode, ok := node.(*ast.Text); ok && entering && node.Parent().Type() == ast.TypeBlock { texts = append(texts, textNode.Segment) } return ast.WalkContinue, nil - }) + } + _ = ast.Walk(mdParser.Parse(mdReader, parser.WithContext(pc)), mdWalker) excerpt := giteautil.EllipsisDisplayString(content[start:], 200) kept, ok := strings.CutSuffix(excerpt, "…") diff --git a/modules/markup/markdown/math/block_renderer.go b/modules/markup/markdown/math/block_renderer.go index e7dee38267a..788643ae8d7 100644 --- a/modules/markup/markdown/math/block_renderer.go +++ b/modules/markup/markdown/math/block_renderer.go @@ -17,8 +17,8 @@ import ( // Block render output: //
...
// -// Keep in mind that there is another "code block" render in "func (r *GoldmarkRender) highlightingRenderer" -// "highlightingRenderer" outputs the math block with extra "chroma" class: +// Keep in mind that there is another "code block" render in "func (r *HTMLRenderer) renderCodeBlock" +// "renderCodeBlock" outputs the math block with extra "chroma" class: //
...
// // Special classes: diff --git a/modules/markup/markdown/transform_codespan.go b/modules/markup/markdown/transform_codespan.go index df4a56fd9e5..1834e0a9f0d 100644 --- a/modules/markup/markdown/transform_codespan.go +++ b/modules/markup/markdown/transform_codespan.go @@ -39,7 +39,7 @@ func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Nod r.Writer.RawWrite(w, value) } case *ColorPreview: - _ = r.renderInternal.FormatWithSafeAttrs(w, ``, v.Color) + _ = r.renderInternal.FormatWithSafeAttrsf(w, ``, v.Color) } } return ast.WalkSkipChildren, nil diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go index 4685028c015..e31c2b6b38e 100644 --- a/modules/markup/orgmode/orgmode.go +++ b/modules/markup/orgmode/orgmode.go @@ -15,7 +15,6 @@ import ( "gitea.dev/modules/markup" "gitea.dev/modules/setting" - "github.com/alecthomas/chroma/v2" "github.com/niklasfasching/go-org/org" ) @@ -58,10 +57,8 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error preAttrs, codeAttrs := highlight.CodeBlockAttributes(lang) lexer := highlight.DetectChromaLexerByFileName("", lang) // don't use content to detect, it is too slow - lexer = chroma.Coalesce(lexer) - sb := &strings.Builder{} - _ = ctx.RenderInternal.FormatWithSafeAttrs(sb, `
`, preAttrs, codeAttrs)
+		_ = ctx.RenderInternal.FormatWithSafeAttrsf(sb, `
`, preAttrs, codeAttrs)
 		_, _ = sb.WriteString(string(highlight.RenderCodeByLexer(lexer, source)))
 		_, _ = sb.WriteString("
") return sb.String()