Fix: validateHSL

This commit is contained in:
eight 2018-11-18 23:55:59 +08:00
parent 28032d25b2
commit 52604f04e9

View File

@ -44,18 +44,17 @@ const colorConverter = (() => {
// Copied from _hexcolor() in parserlib.js // Copied from _hexcolor() in parserlib.js
function validateHex(color) { function validateHex(color) {
return /^#[a-f\d]+$/i.test(color) && [4, 5, 7, 9].some(n => color.length === n)); return /^#[a-f\d]+$/i.test(color) && [4, 5, 7, 9].some(n => color.length === n);
} }
function validateRGB(nums) { function validateRGB(nums) {
const isPercentage = nums[0].endsWith('%'); const isPercentage = nums[0].endsWith('%');
const valid = isPercentage ? validatePercentage : validateNum; const valid = isPercentage ? validatePercentage : validateNum;
return nums.every(valid); return nums.slice(0, 3).every(valid);
} }
function validatePercentage(s) { function validatePercentage(s) {
// FIXME: what about float? const match = s.match(/^(\d+|\d*\.\d+)%$/);
const match = s.match(/^(\d+)%$/);
return match && Number(match[1]) >= 0 && Number(match[1]) <= 100; return match && Number(match[1]) >= 0 && Number(match[1]) <= 100;
} }
@ -63,9 +62,12 @@ const colorConverter = (() => {
return Number(s) >= 0 && Number(s) <= 255; return Number(s) >= 0 && Number(s) <= 255;
} }
// Mod 360 applied to h before function call function validateHSL(nums) {
function validateHSL(h, s, l) { return validateAngle(nums[0]) && nums.slice(1, 3).every(validatePercentage);
return h >= 0 && h <= 360 && [s, l].every(v => v !== false && v >= 0 && v <= 100); }
function validateAngle(s) {
return /^-?(\d+|\d*\.\d+)(deg|grad|rad|turn)?$/i.test(s);
} }
// % converted before function call // % converted before function call
@ -74,28 +76,6 @@ const colorConverter = (() => {
return num >= 0 && num <= 1; return num >= 0 && num <= 1;
} }
function parseNumber(value) {
return /[^\d]/.test(value) ? -1 : parseFloat(value);
}
function parsePercentage(value) {
const val = value.endsWith('%') && parseNumber(value.slice(0, -1));
return val >= 0 && val <= 100 ? val : -1;
}
function parseHue(value) {
const raw = value.replace('.', '').replace(colorConverter.anglesRegexp, '');
let h = parseNumber(raw);
Object.keys(colorConverter.angles).some(angle => {
if (value.endsWith(angle)) {
h *= colorConverter.angles[angle];
return true;
}
return false;
});
return h < 0 ? h : h % 360;
}
function parse(str) { function parse(str) {
if (typeof str !== 'string') return; if (typeof str !== 'string') return;
str = str.trim(); str = str.trim();
@ -136,12 +116,18 @@ const colorConverter = (() => {
} }
const k = first.endsWith('%') ? 2.55 : 1; const k = first.endsWith('%') ? 2.55 : 1;
const [r, g, b] = num.map(s => Math.round(parseFloat(s) * k)); const [r, g, b] = num.map(s => Math.round(parseFloat(s) * k));
return {type: 'rgb', r, g, b, a} : null; return {type: 'rgb', r, g, b, a};
} else { } else {
const h = parseHue(first); if (!validateHSL(num)) {
const s = parsePercentage(num[1]); return null;
const l = parsePercentage(num[2]); }
return validateHSL(h, s, l) ? {type: 'hsl', h, s, l, a} : null; let h = parseFloat(first);
if (first.endsWith('grad')) h *= 360 / 400;
else if (first.endsWith('rad')) h *= 180 / Math.PI;
else if (first.endsWith('turn')) h *= 360;
const s = parseFloat(num[1]);
const l = parseFloat(num[2]);
return {type: 'hsl', h, s, l, a};
} }
} }