fix(theme): clear RGB pulse fallback
- commit
- a47fd09a8f7126727448403e8278978b586a228f
- author
- brice · · 2026-07-17 10:38 UTC
- parent
- bd7ecc4
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +17 -2
M internal/usecase/theme/styles.go +1 -0
| @@ -40,6 +40,7 @@ func PulseColor(base renderer.Style, intensity float64) renderer.Style { | |||
| 40 | 40 | if base.HasForegroundRGB && base.HasBackgroundRGB { | |
| 41 | 41 | style.ForegroundRGB = Blend(base.BackgroundRGB, base.ForegroundRGB, intensity) | |
| 42 | 42 | } else { | |
| 43 | + | style.HasForegroundRGB = false | |
| 43 | 44 | style.Foreground = 244 + int(intensity*11) | |
| 44 | 45 | } | |
| 45 | 46 | return style | |
| @@ -40,6 +40,7 @@ func PulseColor(base renderer.Style, intensity float64) renderer.Style { | |||||
| 40 | if base.HasForegroundRGB && base.HasBackgroundRGB { | 40 | if base.HasForegroundRGB && base.HasBackgroundRGB { | ||
| 41 | style.ForegroundRGB = Blend(base.BackgroundRGB, base.ForegroundRGB, intensity) | 41 | style.ForegroundRGB = Blend(base.BackgroundRGB, base.ForegroundRGB, intensity) | ||
| 42 | } else { | 42 | } else { | ||
| 43 | + | style.HasForegroundRGB = false | |||
| 43 | style.Foreground = 244 + int(intensity*11) | 44 | style.Foreground = 244 + int(intensity*11) | ||
| 44 | } | 45 | } | ||
| 45 | return style | 46 | return style | ||
M internal/usecase/theme/styles_test.go +14 -0
| @@ -59,6 +59,8 @@ func TestPulseColor(t *testing.T) { | |||
| 59 | 59 | HasUnderlineColorRGB: false, | |
| 60 | 60 | } | |
| 61 | 61 | indexedBase := renderer.Style{Foreground: -1, Background: -1, Inverse: true} | |
| 62 | + | mixedBase := rgbBase | |
| 63 | + | mixedBase.HasBackgroundRGB = false | |
| 62 | 64 | ||
| 63 | 65 | tests := []struct { | |
| 64 | 66 | name string | |
| @@ -98,6 +100,18 @@ func TestPulseColor(t *testing.T) { | |||
| 98 | 100 | return style | |
| 99 | 101 | }(), | |
| 100 | 102 | }, | |
| 103 | + | { | |
| 104 | + | name: "RGB foreground without RGB background uses indexed grayscale", | |
| 105 | + | base: mixedBase, | |
| 106 | + | intensity: 0.5, | |
| 107 | + | want: func() renderer.Style { | |
| 108 | + | style := mixedBase | |
| 109 | + | style.Bold = true | |
| 110 | + | style.HasForegroundRGB = false | |
| 111 | + | style.Foreground = 249 | |
| 112 | + | return style | |
| 113 | + | }(), | |
| 114 | + | }, | |
| 101 | 115 | { | |
| 102 | 116 | name: "indexed color uses xterm grayscale start", | |
| 103 | 117 | base: indexedBase, | |
| @@ -59,6 +59,8 @@ func TestPulseColor(t *testing.T) { | |||||
| 59 | HasUnderlineColorRGB: false, | 59 | HasUnderlineColorRGB: false, | ||
| 60 | } | 60 | } | ||
| 61 | indexedBase := renderer.Style{Foreground: -1, Background: -1, Inverse: true} | 61 | indexedBase := renderer.Style{Foreground: -1, Background: -1, Inverse: true} | ||
| 62 | + | mixedBase := rgbBase | |||
| 63 | + | mixedBase.HasBackgroundRGB = false | |||
| 62 | 64 | ||||
| 63 | tests := []struct { | 65 | tests := []struct { | ||
| 64 | name string | 66 | name string | ||
| @@ -98,6 +100,18 @@ func TestPulseColor(t *testing.T) { | |||||
| 98 | return style | 100 | return style | ||
| 99 | }(), | 101 | }(), | ||
| 100 | }, | 102 | }, | ||
| 103 | + | { | |||
| 104 | + | name: "RGB foreground without RGB background uses indexed grayscale", | |||
| 105 | + | base: mixedBase, | |||
| 106 | + | intensity: 0.5, | |||
| 107 | + | want: func() renderer.Style { | |||
| 108 | + | style := mixedBase | |||
| 109 | + | style.Bold = true | |||
| 110 | + | style.HasForegroundRGB = false | |||
| 111 | + | style.Foreground = 249 | |||
| 112 | + | return style | |||
| 113 | + | }(), | |||
| 114 | + | }, | |||
| 101 | { | 115 | { | ||
| 102 | name: "indexed color uses xterm grayscale start", | 116 | name: "indexed color uses xterm grayscale start", | ||
| 103 | base: indexedBase, | 117 | base: indexedBase, | ||
M internal/usecase/theme/theme.go +2 -2
| @@ -107,8 +107,8 @@ func parseXColorComponent(s string) (uint8, bool) { | |||
| 107 | 107 | if err != nil { | |
| 108 | 108 | return 0, false | |
| 109 | 109 | } | |
| 110 | - | max := uint64((1 << (4 * len(s))) - 1) | |
| 111 | - | return uint8(value * 255 / max), true | |
| 110 | + | maxValue := uint64((1 << (4 * len(s))) - 1) | |
| 111 | + | return uint8(value * 255 / maxValue), true | |
| 112 | 112 | } | |
| 113 | 113 | ||
| 114 | 114 | func parseHexByte(s string) (uint8, bool) { | |
| @@ -107,8 +107,8 @@ func parseXColorComponent(s string) (uint8, bool) { | |||||
| 107 | if err != nil { | 107 | if err != nil { | ||
| 108 | return 0, false | 108 | return 0, false | ||
| 109 | } | 109 | } | ||
| 110 | - | max := uint64((1 << (4 * len(s))) - 1) | 110 | + | maxValue := uint64((1 << (4 * len(s))) - 1) |
| 111 | - | return uint8(value * 255 / max), true | 111 | + | return uint8(value * 255 / maxValue), true |
| 112 | } | 112 | } | ||
| 113 | 113 | ||||
| 114 | func parseHexByte(s string) (uint8, bool) { | 114 | func parseHexByte(s string) (uint8, bool) { | ||