Files
Gitea/modules/highlight/highlight_test.go
Moritz Jörg 89bfddc5c2 Normalize guessed languages for code highlighting (#36450)
For when Enry correctly recognized the language, but returns the
language name in a way that isn't recognized by chroma.

Resolves https://github.com/go-gitea/gitea/issues/22443

---------

Co-authored-by: Moritz Jörg <moritz.jorg@oceanbox.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-01-25 14:02:16 +00:00

235 lines
5.0 KiB
Go

// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package highlight
import (
"html/template"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func lines(s string) (out []template.HTML) {
// "" => [], "a" => ["a"], "a\n" => ["a\n"], "a\nb" => ["a\n", "b"] (each line always includes EOL "\n" if it exists)
out = make([]template.HTML, 0)
s = strings.ReplaceAll(strings.ReplaceAll(strings.TrimSpace(s), "\n", ""), `\n`, "\n")
for {
if p := strings.IndexByte(s, '\n'); p != -1 {
out = append(out, template.HTML(s[:p+1]))
s = s[p+1:]
} else {
break
}
}
if s != "" {
out = append(out, template.HTML(s))
}
return out
}
func TestFile(t *testing.T) {
tests := []struct {
name string
code string
want []template.HTML
lexerName string
}{
{
name: "empty.py",
code: "",
want: lines(""),
lexerName: "Python",
},
{
name: "empty.js",
code: "",
want: lines(""),
lexerName: "JavaScript",
},
{
name: "empty.yaml",
code: "",
want: lines(""),
lexerName: "YAML",
},
{
name: "tags.txt",
code: "<>",
want: lines("&lt;&gt;"),
lexerName: "Plaintext",
},
{
name: "tags.py",
code: "<>",
want: lines(`<span class="o">&lt;</span><span class="o">&gt;</span>`),
lexerName: "Python",
},
{
name: "eol-no.py",
code: "a=1",
want: lines(`<span class="n">a</span><span class="o">=</span><span class="mi">1</span>`),
lexerName: "Python",
},
{
name: "eol-newline1.py",
code: "a=1\n",
want: lines(`<span class="n">a</span><span class="o">=</span><span class="mi">1</span>\n`),
lexerName: "Python",
},
{
name: "eol-newline2.py",
code: "a=1\n\n",
want: lines(`
<span class="n">a</span><span class="o">=</span><span class="mi">1</span>\n
\n
`,
),
lexerName: "Python",
},
{
name: "empty-line-with-space.py",
code: strings.ReplaceAll(strings.TrimSpace(`
def:
a=1
b=''
{space}
c=2
`), "{space}", " "),
want: lines(`
<span class="n">def</span><span class="p">:</span>\n
<span class="n">a</span><span class="o">=</span><span class="mi">1</span>\n
\n
<span class="n">b</span><span class="o">=</span><span class="sa"></span><span class="s1">&#39;</span><span class="s1">&#39;</span>\n
\n
<span class="n">c</span><span class="o">=</span><span class="mi">2</span>`,
),
lexerName: "Python",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out, lexerName, err := RenderFullFile(tt.name, "", []byte(tt.code))
assert.NoError(t, err)
assert.Equal(t, tt.want, out)
assert.Equal(t, tt.lexerName, lexerName)
})
}
}
func TestPlainText(t *testing.T) {
tests := []struct {
name string
code string
want []template.HTML
}{
{
name: "empty.py",
code: "",
want: lines(""),
},
{
name: "tags.py",
code: "<>",
want: lines("&lt;&gt;"),
},
{
name: "eol-no.py",
code: "a=1",
want: lines(`a=1`),
},
{
name: "eol-newline1.py",
code: "a=1\n",
want: lines(`a=1\n`),
},
{
name: "eol-newline2.py",
code: "a=1\n\n",
want: lines(`
a=1\n
\n
`),
},
{
name: "empty-line-with-space.py",
code: strings.ReplaceAll(strings.TrimSpace(`
def:
a=1
b=''
{space}
c=2
`), "{space}", " "),
want: lines(`
def:\n
a=1\n
\n
b=&#39;&#39;\n
\n
c=2`),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := RenderPlainText([]byte(tt.code))
assert.Equal(t, tt.want, out)
})
}
}
func TestUnsafeSplitHighlightedLines(t *testing.T) {
ret := UnsafeSplitHighlightedLines("")
assert.Empty(t, ret)
ret = UnsafeSplitHighlightedLines("a")
assert.Len(t, ret, 1)
assert.Equal(t, "a", string(ret[0]))
ret = UnsafeSplitHighlightedLines("\n")
assert.Len(t, ret, 1)
assert.Equal(t, "\n", string(ret[0]))
ret = UnsafeSplitHighlightedLines("<span>a</span>\n<span>b\n</span>")
assert.Len(t, ret, 2)
assert.Equal(t, "<span>a</span>\n", string(ret[0]))
assert.Equal(t, "<span>b\n</span>", string(ret[1]))
}
func TestGetChromaLexer(t *testing.T) {
globalVars().highlightMapping[".my-html"] = "HTML"
t.Cleanup(func() { delete(globalVars().highlightMapping, ".my-html") })
cases := []struct {
fileName string
language string
content string
expected string
}{
{"test.py", "", "", "Python"},
{"any-file", "javascript", "", "JavaScript"},
{"any-file", "", "/* vim: set filetype=python */", "Python"},
{"any-file", "", "", "fallback"},
{"test.fs", "", "", "Forth"},
{"test.fs", "F#", "", "FSharp"},
{"test.fs", "", "let x = 1", "FSharp"},
{"test.c", "", "", "C"},
{"test.C", "", "", "C++"},
{"OLD-CODE.PAS", "", "", "ObjectPascal"},
{"test.my-html", "", "", "HTML"},
}
for _, c := range cases {
lexer := GetChromaLexerWithFallback(c.fileName, c.language, []byte(c.content))
if assert.NotNil(t, lexer, "case: %+v", c) {
assert.Equal(t, c.expected, lexer.Config().Name, "case: %+v", c)
}
}
}