* Validate UserCSS meta colors. Fixes #554 * Add suggestions & optimize code * Fix parsePercentage return value * cleanup * Fix: remove unused variable * Fix: validate function should return a boolean * Revert indent * Fix: cleaner validateRGB * Fix: validateHSL * Fix: validateAlpha * Cleanup * Fix: remove invalid comment * Limit color channels to integers
This commit is contained in:
		
							parent
							
								
									7261a074cd
								
							
						
					
					
						commit
						7ea0200234
					
				|  | @ -42,6 +42,41 @@ const colorConverter = (() => { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // Copied from _hexcolor() in parserlib.js
 | ||||
|   function validateHex(color) { | ||||
|     return /^#[a-f\d]+$/i.test(color) && [4, 5, 7, 9].some(n => color.length === n); | ||||
|   } | ||||
| 
 | ||||
|   function validateRGB(nums) { | ||||
|     const isPercentage = nums[0].endsWith('%'); | ||||
|     const valid = isPercentage ? validatePercentage : validateNum; | ||||
|     return nums.slice(0, 3).every(valid); | ||||
|   } | ||||
| 
 | ||||
|   function validatePercentage(s) { | ||||
|     const match = s.match(/^(\d+|\d*\.\d+)%$/); | ||||
|     return match && Number(match[1]) >= 0 && Number(match[1]) <= 100; | ||||
|   } | ||||
| 
 | ||||
|   function validateNum(s) { | ||||
|     return /^\d+$/.test(s) && Number(s) >= 0 && Number(s) <= 255; | ||||
|   } | ||||
| 
 | ||||
|   function validateHSL(nums) { | ||||
|     return validateAngle(nums[0]) && nums.slice(1, 3).every(validatePercentage); | ||||
|   } | ||||
| 
 | ||||
|   function validateAngle(s) { | ||||
|     return /^-?(\d+|\d*\.\d+)(deg|grad|rad|turn)?$/i.test(s); | ||||
|   } | ||||
| 
 | ||||
|   function validateAlpha(alpha) { | ||||
|     if (alpha.endsWith('%')) { | ||||
|       return validatePercentage(alpha); | ||||
|     } | ||||
|     return Number(alpha) >= 0 && Number(alpha) <= 1; | ||||
|   } | ||||
| 
 | ||||
|   function parse(str) { | ||||
|     if (typeof str !== 'string') return; | ||||
|     str = str.trim(); | ||||
|  | @ -54,6 +89,9 @@ const colorConverter = (() => { | |||
|     } | ||||
| 
 | ||||
|     if (str[0] === '#') { | ||||
|       if (!validateHex(str)) { | ||||
|         return null; | ||||
|       } | ||||
|       str = str.slice(1); | ||||
|       const [r, g, b, a = 255] = str.length <= 4 ? | ||||
|         str.match(/(.)/g).map(c => parseInt(c + c, 16)) : | ||||
|  | @ -67,16 +105,23 @@ const colorConverter = (() => { | |||
|     const comma = value.includes(',') && !value.includes('/'); | ||||
|     const num = value.split(comma ? /\s*,\s*/ : /\s+(?!\/)|\s*\/\s*/); | ||||
|     if (num.length < 3 || num.length > 4) return; | ||||
|     if (num[3] && !validateAlpha(num[3])) return null; | ||||
| 
 | ||||
|     let a = !num[3] ? 1 : parseFloat(num[3]) / (num[3].endsWith('%') ? 100 : 1); | ||||
|     if (isNaN(a)) a = 1; | ||||
| 
 | ||||
|     const first = num[0]; | ||||
|     if (/rgb/i.test(type)) { | ||||
|       if (!validateRGB(num)) { | ||||
|         return null; | ||||
|       } | ||||
|       const k = first.endsWith('%') ? 2.55 : 1; | ||||
|       const [r, g, b] = num.map(s => parseFloat(s) * k); | ||||
|       const [r, g, b] = num.map(s => Math.round(parseFloat(s) * k)); | ||||
|       return {type: 'rgb', r, g, b, a}; | ||||
|     } else { | ||||
|       if (!validateHSL(num)) { | ||||
|         return null; | ||||
|       } | ||||
|       let h = parseFloat(first); | ||||
|       if (first.endsWith('grad')) h *= 360 / 400; | ||||
|       else if (first.endsWith('rad')) h *= 180 / Math.PI; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user