From 2b42fdaa2617a0cd348000817afd5d6b01ea4171 Mon Sep 17 00:00:00 2001 From: TurtleArmy Date: Sun, 12 Apr 2026 18:30:30 +0200 Subject: [PATCH] feat(ui): Fix comma separated attributes in code blocks language preventing syntax-highlighting (#12056) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, forgejo does not support syntax highlighting code-blocks that have comma separated attributes after the language. This is a pattern sometimes seen in Rust code blocks, with tests like this: \`\`\`rust #[test] fn run_this_test() { /* ... */ } \`\`\` \`\`\`rust,ignore #[test] fn skip_this_test() { /* ... */ } \`\`\` Currently, forgejo only does syntax highlighting in the first case: ```rust #[test] fn run_this_test() { /* ... */ } ``` ```rust,ignore #[test] fn skip_this_test() { /* ... */ } ``` An example of this causing problems can be seen in this commit (https://codeberg.org/zesterer/ariadne/commit/5be9c5b7d2a2eeeefbc014a1ba873b53f1afaee9) causing the following issue (https://codeberg.org/zesterer/ariadne/issues/188). This PR fixes fixes the second case not getting proper syntax highlighting. Co-authored-by: TurtleArmy <44322335+TurtleArmyMc@users.noreply.github.com> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12056 Reviewed-by: Gusted Reviewed-by: Ellen Εμίλια Άννα Zscheile Co-authored-by: TurtleArmy Co-committed-by: TurtleArmy --- modules/markup/markdown/goldmark.go | 2 ++ modules/markup/markdown/markdown_test.go | 24 +++++++++++++++++ .../markdown/transform_codeblock_lang.go | 27 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 modules/markup/markdown/transform_codeblock_lang.go diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 1ea3375ab5..aec710fd46 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -90,6 +90,8 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa } case *ast.RawHTML: g.transformRawHTML(ctx, v, reader) + case *ast.FencedCodeBlock: + g.transformCodeblockLanguage(v, reader) } return ast.WalkContinue, nil }) diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index 61ded3cedc..fc4a515f72 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -1488,3 +1488,27 @@ func TestCallout(t *testing.T) {

Bad stuff is brewing here

`) } + +func TestCodeblockLanguageStripping(t *testing.T) { + test := func(input, expected string) { + buffer, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, input) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) + } + + // Unstripped + test( + "```rust\n"+ + "fn main() {}\n"+ + "```", + `
fn main() {}
+
`) + + // Stripped + test( + "```rust,ignore\n"+ + "fn main() {}\n"+ + "```", + `
fn main() {}
+
`) +} diff --git a/modules/markup/markdown/transform_codeblock_lang.go b/modules/markup/markdown/transform_codeblock_lang.go new file mode 100644 index 0000000000..2c90373c4e --- /dev/null +++ b/modules/markup/markdown/transform_codeblock_lang.go @@ -0,0 +1,27 @@ +// Copyright 2026 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown + +import ( + "bytes" + + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/text" +) + +func (g *ASTTransformer) transformCodeblockLanguage(v *ast.FencedCodeBlock, reader text.Reader) { + src := reader.Source() + info := v.Info.Segment.Value(src) + // Strip language after commas + // + // For example, + // ```rust,ignore + // ... + // ``` + // Should have a language of "rust", not "rust,ignore" + if i := bytes.IndexByte(info, ','); i != -1 { + start := v.Info.Segment.Start + v.Info = ast.NewTextSegment(text.NewSegment(start, start+i)) + } +}