mirror of
				https://github.com/go-gitea/gitea
				synced 2025-09-28 03:28:13 +00:00 
			
		
		
		
	Adds the `flat-square` style to action badges. Styles can be selected by adding `?style=<style>` to the badge endpoint. If no style query is given, or if the query is invalid, the style defaults to `flat`. --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
		
			
				
	
	
		
			130 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2024 The Gitea Authors. All rights reserved.
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| package badge
 | |
| 
 | |
| import (
 | |
| 	"strings"
 | |
| 	"sync"
 | |
| 	"unicode"
 | |
| 
 | |
| 	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
 | |
| 
 | |
| type Text struct {
 | |
| 	text  string
 | |
| 	width int
 | |
| 	x     int
 | |
| }
 | |
| 
 | |
| func (t Text) Text() string {
 | |
| 	return t.text
 | |
| }
 | |
| 
 | |
| func (t Text) Width() int {
 | |
| 	return t.width
 | |
| }
 | |
| 
 | |
| func (t Text) X() int {
 | |
| 	return t.x
 | |
| }
 | |
| 
 | |
| func (t Text) TextLength() int {
 | |
| 	return int(float64(t.width-defaultOffset) * 10)
 | |
| }
 | |
| 
 | |
| type Badge struct {
 | |
| 	IDPrefix   string
 | |
| 	FontFamily string
 | |
| 	Color      string
 | |
| 	FontSize   int
 | |
| 	Label      Text
 | |
| 	Message    Text
 | |
| }
 | |
| 
 | |
| func (b Badge) Width() int {
 | |
| 	return b.Label.width + b.Message.width
 | |
| }
 | |
| 
 | |
| // Style follows https://shields.io/badges
 | |
| const (
 | |
| 	StyleFlat       = "flat"
 | |
| 	StyleFlatSquare = "flat-square"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	defaultOffset     = 10
 | |
| 	defaultFontSize   = 11
 | |
| 	DefaultColor      = "#9f9f9f" // Grey
 | |
| 	DefaultFontFamily = "DejaVu Sans,Verdana,Geneva,sans-serif"
 | |
| 	DefaultStyle      = StyleFlat
 | |
| )
 | |
| 
 | |
| 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
 | |
| })
 | |
| 
 | |
| // GenerateBadge generates badge with given template
 | |
| func GenerateBadge(label, message, color string) Badge {
 | |
| 	lw := calculateTextWidth(label) + defaultOffset
 | |
| 	mw := calculateTextWidth(message) + defaultOffset
 | |
| 
 | |
| 	lx := lw * 5
 | |
| 	mx := lw*10 + mw*5 - 10
 | |
| 	return Badge{
 | |
| 		FontFamily: DefaultFontFamily,
 | |
| 		Label: Text{
 | |
| 			text:  label,
 | |
| 			width: lw,
 | |
| 			x:     lx,
 | |
| 		},
 | |
| 		Message: Text{
 | |
| 			text:  message,
 | |
| 			width: mw,
 | |
| 			x:     mx,
 | |
| 		},
 | |
| 		FontSize: defaultFontSize * 10,
 | |
| 		Color:    color,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func calculateTextWidth(text string) int {
 | |
| 	width := 0
 | |
| 	widthData := GlobalVars().DejaVuGlyphWidthData
 | |
| 	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
 | |
| }
 |