diff options
| author | Tommaso Negri <me@tommasongr.com> | 2026-10-14 22:21:05 +0200 |
|---|---|---|
| committer | Tommaso Negri <me@tommasongr.com> | 2026-10-14 22:21:05 +0200 |
| commit | 4942df3a59c0dd7c95b82727f8b03ddf80657973 (patch) | |
| tree | 0d1395de2bce8257e251ed78ab921ec3da7762f8 /Sources | |
| parent | ec076ee6e315e6059545d0364a329cdb4b80b306 (diff) | |
| download | bar-4942df3a59c0dd7c95b82727f8b03ddf80657973.tar.gz bar-4942df3a59c0dd7c95b82727f8b03ddf80657973.zip | |
improve hex color conversion
Diffstat (limited to 'Sources')
| -rw-r--r-- | Sources/bar/Models/Color+Hex.swift | 14 | ||||
| -rw-r--r-- | Sources/bar/bar.docc/customisation.md | 3 |
2 files changed, 11 insertions, 6 deletions
diff --git a/Sources/bar/Models/Color+Hex.swift b/Sources/bar/Models/Color+Hex.swift index 4f82e78..9d8fc36 100644 --- a/Sources/bar/Models/Color+Hex.swift +++ b/Sources/bar/Models/Color+Hex.swift @@ -7,10 +7,8 @@ extension SwiftUI.Color { /// `#RRGGBB`, and `#RRGGBBAA`. Single-digit components are expanded by /// repeating the digit. When present, the trailing digits encode alpha /// (opacity); otherwise opacity defaults to `1`. Surrounding whitespace is - /// trimmed. Unsupported lengths resolve to opaque black. At supported - /// lengths, Scanner may parse only a leading hexadecimal portion; its - /// success result is not checked. Invalid characters therefore do not - /// reliably produce opaque black (alpha formats can be transparent). + /// trimmed. Unsupported lengths or any non-hexadecimal characters resolve + /// to opaque black. /// /// - Parameter code: A hex color code. static func hex(_ code: String) -> SwiftUI.Color { @@ -19,8 +17,12 @@ extension SwiftUI.Color { sanitized.removeFirst() } - var rgba: UInt64 = 0 - Scanner(string: sanitized).scanHexInt64(&rgba) + // Restrict input to ASCII hex digits; integer conversion also accepts signs. + guard sanitized.utf8.allSatisfy({ + (48...57).contains($0) || (65...70).contains($0) || (97...102).contains($0) + }), let rgba = UInt64(sanitized, radix: 16) else { + return Color(.sRGB, red: 0, green: 0, blue: 0, opacity: 1) + } let red: Double let green: Double diff --git a/Sources/bar/bar.docc/customisation.md b/Sources/bar/bar.docc/customisation.md index f5d5195..cdf48d9 100644 --- a/Sources/bar/bar.docc/customisation.md +++ b/Sources/bar/bar.docc/customisation.md @@ -36,6 +36,9 @@ static let foreground: Color = .hex("#CDD6F4") ``` Supported formats (the leading `#` is optional): `#RGB`, `#RGBA`, `#RRGGBB`, `#RRGGBBAA`. +Surrounding whitespace is ignored, and letters can be uppercase or lowercase. +Short components repeat their digit (`#3aF` becomes `#33AAFF`); trailing alpha sets opacity, which otherwise defaults to 1. +Unsupported lengths or invalid characters produce opaque black. ## Spacing |
