Files

130 lines
2.8 KiB
Go
Raw Permalink Normal View History

2024-02-28 01:56:18 +08:00
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package badge
import (
2025-03-28 16:12:47 +01:00
"strings"
2025-04-01 11:42:10 +02:00
"sync"
2025-03-28 16:12:47 +01:00
"unicode"
2024-02-28 01:56:18 +08:00
actions_model "code.gitea.io/gitea/models/actions"
)
// The Badge layout: |offset|label|message|
// We use 10x scale to calculate more precisely
// Then scale down to normal size in tmpl file
2025-03-28 16:12:47 +01:00
type Text struct {
2024-02-28 01:56:18 +08:00
text string
width int
x int
}
2025-03-28 16:12:47 +01:00
func (t Text) Text() string {
return t.text
2024-02-28 01:56:18 +08:00
}
2025-03-28 16:12:47 +01:00
func (t Text) Width() int {
return t.width
2024-02-28 01:56:18 +08:00
}
2025-03-28 16:12:47 +01:00
func (t Text) X() int {
return t.x
2024-02-28 01:56:18 +08:00
}
2025-03-28 16:12:47 +01:00
func (t Text) TextLength() int {
return int(float64(t.width-defaultOffset) * 10)
2024-02-28 01:56:18 +08:00
}
type Badge struct {
2025-03-28 16:12:47 +01:00
IDPrefix string
FontFamily string
Color string
FontSize int
Label Text
Message Text
2024-02-28 01:56:18 +08:00
}
func (b Badge) Width() int {
return b.Label.width + b.Message.width
}
2025-04-01 11:42:10 +02:00
// Style follows https://shields.io/badges
const (
StyleFlat = "flat"
StyleFlatSquare = "flat-square"
)
2024-02-28 01:56:18 +08:00
const (
2025-03-28 16:12:47 +01:00
defaultOffset = 10
defaultFontSize = 11
DefaultColor = "#9f9f9f" // Grey
DefaultFontFamily = "DejaVu Sans,Verdana,Geneva,sans-serif"
2025-04-01 11:42:10 +02:00
DefaultStyle = StyleFlat
2024-02-28 01:56:18 +08:00
)
2025-04-01 11:42:10 +02:00
var GlobalVars = sync.OnceValue(func() (ret struct {
StatusColorMap map[actions_model.Status]string
DejaVuGlyphWidthData map[rune]uint8
AllStyles []string
},
) {
ret.StatusColorMap = map[actions_model.Status]string{
actions_model.StatusSuccess: "#4c1", // Green
actions_model.StatusSkipped: "#dfb317", // Yellow
actions_model.StatusUnknown: "#97ca00", // Light Green
actions_model.StatusFailure: "#e05d44", // Red
actions_model.StatusCancelled: "#fe7d37", // Orange
actions_model.StatusWaiting: "#dfb317", // Yellow
actions_model.StatusRunning: "#dfb317", // Yellow
actions_model.StatusBlocked: "#dfb317", // Yellow
}
ret.DejaVuGlyphWidthData = dejaVuGlyphWidthDataFunc()
ret.AllStyles = []string{StyleFlat, StyleFlatSquare}
return ret
})
2024-02-28 01:56:18 +08:00
// GenerateBadge generates badge with given template
func GenerateBadge(label, message, color string) Badge {
2025-03-28 16:12:47 +01:00
lw := calculateTextWidth(label) + defaultOffset
mw := calculateTextWidth(message) + defaultOffset
lx := lw * 5
mx := lw*10 + mw*5 - 10
2024-02-28 01:56:18 +08:00
return Badge{
2025-03-28 16:12:47 +01:00
FontFamily: DefaultFontFamily,
Label: Text{
2024-02-28 01:56:18 +08:00
text: label,
width: lw,
2025-03-28 16:12:47 +01:00
x: lx,
2024-02-28 01:56:18 +08:00
},
2025-03-28 16:12:47 +01:00
Message: Text{
2024-02-28 01:56:18 +08:00
text: message,
width: mw,
2025-03-28 16:12:47 +01:00
x: mx,
2024-02-28 01:56:18 +08:00
},
FontSize: defaultFontSize * 10,
Color: color,
}
}
2025-03-28 16:12:47 +01:00
func calculateTextWidth(text string) int {
width := 0
2025-04-01 11:42:10 +02:00
widthData := GlobalVars().DejaVuGlyphWidthData
2025-03-28 16:12:47 +01:00
for _, char := range strings.TrimSpace(text) {
charWidth, ok := widthData[char]
if !ok {
// use the width of 'm' in case of missing glyph width data for a printable character
if unicode.IsPrint(char) {
charWidth = widthData['m']
} else {
charWidth = 0
}
}
width += int(charWidth)
}
return width
}