@@ -96,26 +96,10 @@ def parse_color_to_rgb(
9696 # 1. Normalise tuple/list inputs first
9797 if isinstance (color , (tuple , list )):
9898 ln = len (color )
99+
99100 if ln == 3 :
100- # 3-component tuple/list - DEFAULT TO RGB (most common case)
101- # Only treat as HSL if explicitly float values in 0-1 range for s,l AND h <= 360
102- r_raw , g_raw , b_raw = color
103-
104- # Check if this looks like HSL: h <= 360, s and l are floats in [0,1]
105- if (
106- isinstance (r_raw , (int , float ))
107- and 1 < float (r_raw ) <= 360
108- and isinstance (g_raw , float )
109- and 0.0 <= float (g_raw ) <= 1.0
110- and isinstance (b_raw , float )
111- and 0.0 <= float (b_raw ) <= 1.0
112- and not isinstance (g_raw , int )
113- and not isinstance (b_raw , int )
114- ):
115- # This looks like HSL: (hue, saturation_float, lightness_float)
116- return hsl_to_rgb (color )
117- else :
118- # Default to RGB processing
101+ # Always try RGB first
102+ try :
119103 comps = []
120104 for c in color :
121105 if isinstance (c , (int , float )):
@@ -126,24 +110,38 @@ def parse_color_to_rgb(
126110 elif isinstance (c , float ) and 0.0 <= c <= 255.0 :
127111 comps .append (int (round (c )))
128112 else :
129- raise ValueError (
130- f"RGB component out of range or invalid: { c } "
131- )
113+ raise ValueError (f"RGB component out of range or invalid: { c } " )
132114 elif isinstance (c , str ):
133115 comps .append (int (round (_parse_number_token (c , component = True ))))
134116 else :
135117 raise ValueError (
136118 f"Unsupported RGB component type: { type (c ).__name__ } "
137119 )
138120
139- rgb = tuple (max (0 , min (255 , int (round (x )))) for x in comps )
121+ rgb = tuple (int (round (x )) for x in comps )
122+
140123 if not is_valid_rgb (rgb ):
141- raise ValueError (f"Invalid RGB tuple after parsing: { rgb } " )
124+ raise ValueError (f"RGB component out of range or invalid: { rgb } " )
125+
142126 return rgb
143127
128+
129+ except ValueError as e :
130+ # If this was clearly an RGB range error, do NOT fallback
131+ if "out of range" in str (e ):
132+ raise
133+
134+ # Otherwise, try HSL fallback
135+ try :
136+ return hsl_to_rgb (color )
137+ except Exception :
138+ raise ValueError (
139+ "Invalid color tuple. If you intended HSL, use hsl(...) syntax."
140+ )
141+
142+
144143 elif ln == 4 :
145144 # 4-component tuple: RGBA or HSLA
146- # Heuristic: if any of first 3 values are > 1 or integers, treat as RGBA
147145 r_raw , g_raw , b_raw , a_raw = color
148146
149147 looks_like_rgb = (
@@ -156,18 +154,18 @@ def parse_color_to_rgb(
156154 )
157155
158156 if looks_like_rgb :
159- # Treat as RGBA
160157 r = int (round (_parse_number_token (str (r_raw ), component = True )))
161158 g = int (round (_parse_number_token (str (g_raw ), component = True )))
162159 b = int (round (_parse_number_token (str (b_raw ), component = True )))
163160 a = _parse_number_token (str (a_raw ), component = False )
164161
165- # resolve background
166162 if background is None :
167163 bg_rgb = (255 , 255 , 255 )
168164 else :
169165 bg_rgb = parse_color_to_rgb (background )
166+
170167 return rgba_to_rgb ((r , g , b , a ), background = bg_rgb )
168+
171169 else :
172170 bg_rgb = None
173171 if background is not None :
@@ -176,6 +174,7 @@ def parse_color_to_rgb(
176174 else :
177175 bg_rgb = parse_color_to_rgb (background )
178176 return hsla_to_rgb (color , bg_rgb )
177+
179178 else :
180179 raise ValueError (
181180 f"Tuple/list color must have length 3 (RGB/HSL) or 4 (RGBA/HSLA). Got length { ln } "
0 commit comments