mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-13 06:20:24 +00:00
This resolves https://codeberg.org/forgejo/forgejo/issues/11107. Codeberg doesn't support [Pandoc style code blocks](https://pandoc.org/MANUAL.html#extension-fenced_code_attributes), so only the two of these 3 will have syntax highlighting. \`\`\`haskell qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) \`\`\` \`\`\`haskell {.numberLines} qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) \`\`\` \`\`\`{.numberLines .haskell} qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) \`\`\` ```haskell qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) ``` ```haskell {.numberLines} qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) ``` ```{.numberLines .haskell} qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) ``` This PR adds syntax highlighting to the examples with Pandoc style code blocks. It also adds redundant code to explicitly handle the second case with the trailing attribute syntax, which might be unnecessary since it already works, but I think should be fine to leave in. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12099 Reviewed-by: Ellen Εμίλια Άννα Zscheile <fogti@noreply.codeberg.org> Reviewed-by: Gusted <gusted@noreply.codeberg.org>
57 lines
1.5 KiB
Go
57 lines
1.5 KiB
Go
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package markdown
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/alecthomas/chroma/v2/lexers"
|
|
"github.com/yuin/goldmark/ast"
|
|
"github.com/yuin/goldmark/text"
|
|
)
|
|
|
|
func (g *ASTTransformer) transformCodeblockLanguage(v *ast.FencedCodeBlock, reader text.Reader) {
|
|
if v.Info == nil {
|
|
return
|
|
}
|
|
src := reader.Source()
|
|
info := v.Info.Segment.Value(src)
|
|
|
|
// Parse Pandoc style attributes
|
|
// https://pandoc.org/MANUAL.html#extension-fenced_code_attributes
|
|
//
|
|
// For example,
|
|
// ```{.haskell .numberLines}
|
|
// ...
|
|
// ```
|
|
// Should have a language of "haskell", not "{.haskell .numberLines}"
|
|
if trimmed := bytes.TrimSpace(info); bytes.HasPrefix(trimmed, []byte{'{'}) && bytes.HasSuffix(trimmed, []byte{'}'}) {
|
|
attributes := trimmed[1 : len(trimmed)-1]
|
|
for attribute := range bytes.SplitSeq(attributes, []byte{' '}) {
|
|
if class, found := bytes.CutPrefix(attribute, []byte{'.'}); found {
|
|
if lexer := lexers.Get(string(class)); lexer != nil {
|
|
lang := class
|
|
langInx := bytes.Index(info, lang)
|
|
start := v.Info.Segment.Start + langInx
|
|
end := start + len(lang)
|
|
v.Info = ast.NewTextSegment(text.NewSegment(start, end))
|
|
return
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 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))
|
|
}
|
|
}
|