--- interface Props { weather: string; leadingSeparator?: boolean; } const { weather, leadingSeparator } = Astro.props; type WeatherCategory = | "storm" | "sleet" | "snow" | "rain" | "fog" | "partlyCloudy" | "cloudy" | "clear" | "unknown"; const categoryRules: { category: WeatherCategory; keywords: string[] }[] = [ { category: "storm", keywords: ["thunder", "tstorm", "storm"] }, { category: "sleet", keywords: ["sleet", "freez", "frzg", "mix"] }, { category: "snow", keywords: ["snow", "flurr"] }, { category: "rain", keywords: ["rain", "shower", "drizzle"] }, { category: "fog", keywords: ["fog", "mist", "haze"] }, { category: "partlyCloudy", keywords: ["partly", "variable"] }, { category: "cloudy", keywords: ["overcast", "cloud"] }, { category: "clear", keywords: ["clear", "sunny", "sun", "fair"] }, ]; function categorize(conditions: string): WeatherCategory { const c = conditions.toLowerCase(); for (const rule of categoryRules) { for (const kw of rule.keywords) { if (c.includes(kw)) return rule.category; } } return "unknown"; } const weatherIcons: Partial> = { partlyCloudy: ``, clear: ``, cloudy: ``, storm: ``, rain: ``, snow: ``, sleet: ``, fog: ``, }; const parts = weather.split(",").map((p) => p.trim()); const valid = parts.length >= 4; const qualifierRE = /^(slight chance|chance|isolated|scattered|numerous|widespread|patchy|areas|periods|occasional|frequent)\s+(of\s+)?/i; const trailingQualifierRE = /\s+(likely)$/i; const conditions = valid ? parts[0].replace(qualifierRE, "").replace(trailingQualifierRE, "").trim() : ""; const temperature = valid ? `${parts[1]}°F` : ""; const location = valid ? `${parts[2]}, ${parts[3]}` : ""; const icon = valid ? weatherIcons[categorize(conditions)] : undefined; --- {valid && ( <> {leadingSeparator && } {icon && } {conditions}{" "}{temperature} {location} )}