@@ -27,7 +27,7 @@ const SAFE_COLOR_KEYWORDS = new Set(["black", "white", "transparent", "currentco
|
27 | 27 | const SAFE_COLOR_FUNCTION_PATTERN = |
28 | 28 | /^(?:rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch)\([a-z0-9+\-.,/%\s]+\)$/i; |
29 | 29 | const SAFE_HEX_COLOR_PATTERN = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i; |
30 | | -const SAFE_FONT_FAMILY_PATTERN = /^[a-z0-9\s,'"._-]+(?:,\s*[a-z0-9\s'"._-]+)*$/i; |
| 30 | +const SAFE_FONT_FAMILY_PUNCTUATION = new Set([",", "'", '"', ".", "_", "-"]); |
31 | 31 | |
32 | 32 | const MODE_TOKEN_ORDER = [ |
33 | 33 | "bg", |
@@ -261,12 +261,23 @@ function requireSafeExternalColorValue(value: unknown, label: string) {
|
261 | 261 | throw new Error(`Unsupported tweakcn token: ${label}`); |
262 | 262 | } |
263 | 263 | |
| 264 | +function isSafeFontFamilyCharacter(char: string) { |
| 265 | +const code = char.charCodeAt(0); |
| 266 | +return ( |
| 267 | +(code >= 0x30 && code <= 0x39) || |
| 268 | +(code >= 0x41 && code <= 0x5a) || |
| 269 | +(code >= 0x61 && code <= 0x7a) || |
| 270 | +char === " " || |
| 271 | +SAFE_FONT_FAMILY_PUNCTUATION.has(char) |
| 272 | +); |
| 273 | +} |
| 274 | + |
264 | 275 | function requireSafeFontFamilyValue(value: unknown, label: string) { |
265 | 276 | const normalized = requireSafeCssValue(value, label); |
266 | 277 | if ( |
267 | 278 | normalized.includes("(") || |
268 | 279 | normalized.includes(")") || |
269 | | -!SAFE_FONT_FAMILY_PATTERN.test(normalized) |
| 280 | +!Array.from(normalized).every(isSafeFontFamilyCharacter) |
270 | 281 | ) { |
271 | 282 | throw new Error(`Unsupported tweakcn token: ${label}`); |
272 | 283 | } |
|