snapshot of https://github.com/go-gitea/gitea.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
cache-seeder / prune (push) Has been skipped
cache-seeder / frontend (push) Failing after 3s
cache-seeder / python (push) Failing after 3s
cache-seeder / gobuild (push) Failing after 4s
cache-seeder / lint (bindata, lint-backend) (push) Failing after 3s
giteabot backport / giteabot (push) Has been skipped
giteabot / giteabot (push) Has been skipped
cache-prune / prune (push) Has been skipped
release-nightly-snapcraft / build-and-publish (ubuntu-24.04) (push) Has been cancelled
release-nightly-snapcraft / build-and-publish (ubuntu-24.04-arm) (push) Has been cancelled
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
cron-renovate / cron-renovate (push) Has been skipped

This commit is contained in:
upstream-mirror
2026-09-15 21:41:59 +05:00
commit 52ae0c5802
6280 changed files with 624193 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package console
import (
"bytes"
"io"
"unicode/utf8"
"gitea.dev/modules/markup"
"gitea.dev/modules/setting"
"gitea.dev/modules/typesniffer"
"gitea.dev/modules/util"
trend "github.com/buildkite/terminal-to-html/v3"
)
func init() {
markup.RegisterRenderer(Renderer{})
}
type Renderer struct{}
var _ markup.RendererContentDetector = (*Renderer)(nil)
func (Renderer) Name() string {
return "console"
}
func (Renderer) FileNamePatterns() []string {
return []string{"*.sh-session"}
}
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
return []setting.MarkupSanitizerRule{
{Element: "span", AllowAttr: "class", Regexp: `^term-((fg[ix]?|bg)\d+|container)$`},
}
}
func (Renderer) CanRender(filename string, sniffedType typesniffer.SniffedType, prefetchBuf []byte) bool {
if !sniffedType.IsTextPlain() {
return false
}
s := util.UnsafeBytesToString(prefetchBuf)
rs := []rune(s)
cnt := 0
firstErrPos := -1
isCtrlSep := func(p int) bool {
return p < len(rs) && (rs[p] == ';' || rs[p] == 'm')
}
for i, c := range rs {
if c == 0 {
return false
}
if c == '\x1b' {
match := i+1 < len(rs) && rs[i+1] == '['
if match && (isCtrlSep(i+2) || isCtrlSep(i+3) || isCtrlSep(i+4) || isCtrlSep(i+5)) {
cnt++
}
}
if c == utf8.RuneError && firstErrPos == -1 {
firstErrPos = i
}
}
if firstErrPos != -1 && firstErrPos != len(rs)-1 {
return false
}
return cnt >= 2 // only render it as console output if there are at least two escape sequences
}
// Render renders terminal colors to HTML with all specific handling stuff.
func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error {
buf, err := io.ReadAll(input)
if err != nil {
return err
}
buf = []byte(trend.Render(buf))
buf = bytes.ReplaceAll(buf, []byte("\n"), []byte(`<br>`))
_, err = output.Write(buf)
return err
}

View File

@@ -0,0 +1,46 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package console
import (
"strings"
"testing"
"gitea.dev/modules/markup"
"gitea.dev/modules/typesniffer"
"github.com/stretchr/testify/assert"
)
func TestRenderConsole(t *testing.T) {
cases := []struct {
input string
expected string
}{
{"\x1b[37m\x1b[40mnpm\x1b[0m \x1b[0m\x1b[32minfo\x1b[0m \x1b[0m\x1b[35mit worked if it ends with\x1b[0m ok", `<span class="term-fg37 term-bg40">npm</span> <span class="term-fg32">info</span> <span class="term-fg35">it worked if it ends with</span> ok`},
{"\x1b[1;2m \x1b[123m 啊", `<span class="term-fg2"> 啊</span>`},
{"\x1b[1;2m \x1b[123m \xef", `<span class="term-fg2"> <20></span>`},
{"\x1b[1;2m \x1b[123m \xef \xef", ``},
{"\x1b[12", ``},
{"\x1b[1", ``},
{"\x1b[FOO\x1b[", ``},
{"\x1b[mFOO\x1b[m", `FOO`},
}
var render Renderer
for i, c := range cases {
var buf strings.Builder
st := typesniffer.DetectContentType([]byte(c.input))
canRender := render.CanRender("test", st, []byte(c.input))
if c.expected == "" {
assert.False(t, canRender, "case %d: expected not to render", i)
continue
}
assert.True(t, canRender)
err := render.Render(markup.NewRenderContext(t.Context()), strings.NewReader(c.input), &buf)
assert.NoError(t, err)
assert.Equal(t, c.expected, buf.String())
}
}