mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 11:01:25 +01:00
Lists had no header, wrapped every row once a title was longer than the terminal, and were space-padded when piped, so cut -f and awk -F'\t' could not split them and empty cells collapsed. terminal.Table now takes column specs and a Display. On a terminal it prints an uppercase header, aligns columns two spaces apart and shrinks flexible columns, widest first, to Streams.Width (the terminal, then $COLUMNS, then 80), cutting by display width with "…". States use the terminal's ANSI 16 colors, hex colors fall back to the 256-color palette unless COLORTERM advertises 24-bit, and OSC 8 links appear only on the first column, independently of color (TEA_HYPERLINKS=auto|always|never). Piped tables are tab-separated without header, color or links, and times are RFC3339 UTC instead of "about 2 hours ago". terminal.View lays out single resources (title, badges, metadata, fields, body, footer URL) and renders markdown bodies with glamour on a terminal only (TEA_MARKDOWN=raw keeps them raw). Shared formatters cover relative times, timestamps, sizes, durations and status icons. In the app, writeTable and writeView are the new list and view writers: a "Showing N of M …" context line, an empty-state message on stderr and the next-page hint. writeList, writeItem and batch keep working and now render through the new table: tab-separated when piped, truncated at the widest column on a terminal, with headers for issue list and pr list. Signed-off-by: bircni <bircni@icloud.com>
55 lines
1.6 KiB
Go
55 lines
1.6 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package terminal
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"charm.land/glamour/v2"
|
|
"charm.land/glamour/v2/styles"
|
|
)
|
|
|
|
// MarkdownEnabled resolves the markdown preference: raw never renders, and auto renders on TTY stdout.
|
|
func MarkdownEnabled(preference string, outTTY bool) bool {
|
|
return outTTY && preference != "raw"
|
|
}
|
|
|
|
// glamourLinks matches the OSC 8 hyperlinks that glamour writes for markdown links.
|
|
var glamourLinks = regexp.MustCompile("\x1b\\]8;[^\x07\x1b]*(?:\x07|\x1b\\\\)")
|
|
|
|
// Markdown renders sanitized markdown for d: wrapped to its width (80 when unknown), colored or plain,
|
|
// with links only when d allows them. It keeps line breaks like Gitea does, and returns the sanitized
|
|
// text unrendered if rendering fails.
|
|
func Markdown(text string, d Display) string {
|
|
text = SafeText(text)
|
|
width := d.Width
|
|
if width <= 0 {
|
|
width = 80
|
|
}
|
|
style := styles.NoTTYStyleConfig
|
|
if d.Color {
|
|
style = styles.DarkStyleConfig
|
|
// The terminal's own text color keeps body text readable on light backgrounds too.
|
|
style.Document.Color = nil
|
|
}
|
|
renderer, err := glamour.NewTermRenderer(glamour.WithStyles(style), glamour.WithWordWrap(width), glamour.WithPreservedNewLines())
|
|
if err != nil {
|
|
return text
|
|
}
|
|
rendered, err := renderer.Render(text)
|
|
if err != nil {
|
|
return text
|
|
}
|
|
if !d.Links {
|
|
rendered = glamourLinks.ReplaceAllString(rendered, "")
|
|
}
|
|
// glamour pads every line to the full width.
|
|
lines := strings.Split(rendered, "\n")
|
|
for i, line := range lines {
|
|
lines[i] = strings.TrimRight(line, " ")
|
|
}
|
|
return strings.Trim(strings.Join(lines, "\n"), "\n")
|
|
}
|