UNPKG

gradient-utils

Version:
163 lines (160 loc) 5.77 kB
'use strict'; const NUMBER_REGEX = /[+-]?(?:[0-9]+(?:[.][0-9]+)?(?:[eE][+-]?[0-9]+)?|[.][0-9]+(?:[eE][+-]?[0-9]+)?)/; const START_WITH_NUMBER_REGEX = new RegExp(`^${NUMBER_REGEX.source}`); const DELIMITER_REGEX = /(^$)|(^\W)/; const UNIT_REGEX = /^(?<unit>[a-z]+|%)(?:$|[/s,); ])/; const START_WITH_SIDE_OR_CORNER_REGEX = /^to\s+(?:(?:left|right)(?:\s+(?:top|bottom))?|(?:top|bottom)(?:\s+(?:right|left))?)/; const START_WITH_INTERPOLATION = /^in\s+(?<interpolation>[a-z][^,]+),/; const START_WITH_FUNCTION_REGEX = /^[a-z][a-z0-9-]+\(/; const START_NAMED_COLOR_REGEX = /^(?<color>[a-z]+|currentColor)(?:$|\W)/; const START_HEX_REGEX = /^(?<color>#((?<short>[0-9a-f]{3})(?<shortA>[0-9a-f]{1})?|(?<long>[0-9a-f]{6})(?<longA>[0-9a-f]{2})?))(?:$|\W)/; const ANGLE_UNITS = ['deg', 'turn', 'grad', 'rad']; const isAngleUnit = (unit) => ANGLE_UNITS.includes(unit); const extractStartValueWithUnit = (source, zeroUnit = '') => { const match = source.match(START_WITH_NUMBER_REGEX); if (match && match[0]) { const sourceValue = match[0]; let value = Number(sourceValue); if (value === Number.NEGATIVE_INFINITY) { value = -Number.MAX_VALUE; } else if (value === Number.POSITIVE_INFINITY) { value = Number.MAX_VALUE; } source = source.substring(sourceValue.length); const unitMatch = source.match(UNIT_REGEX); if (unitMatch && unitMatch.groups) { const unit = unitMatch.groups.unit; return { value, sourceValue: sourceValue + unit, source: source.substring(unit.length).trim(), unit: unit, }; } if (value === 0 && DELIMITER_REGEX.test(source)) { return { value, sourceValue: sourceValue, source: source.trim(), unit: zeroUnit, }; } } return null; }; const extractStartComma = (source) => { source = source.trim(); if (!source.startsWith(',')) { return null; } return source.substring(1).trim(); }; const extractStartWithFunction = (source) => { const match = source.match(START_WITH_FUNCTION_REGEX); if (match) { let openedCount = 1; let i = match[0].length; while (i < source.length && openedCount > 0) { if (source.charAt(i) === '(') { openedCount++; } else if (source.charAt(i) === ')') { openedCount--; } i++; } if (openedCount > 0) { return null; } return { function: source.substring(0, i), source: source.substring(i).trim(), }; } return null; }; const extractStartWithHex = (source) => { const match = source.match(START_HEX_REGEX); if (match && match.groups) { const alphaHex = match.groups.longA ? match.groups.longA : match.groups.shortA ? match.groups.shortA.repeat(2) : null; const alpha = alphaHex ? parseInt(alphaHex, 16) / 255 : undefined; const color = '#' + (match.groups.short || match.groups.long); return { color, alpha, source: source.substring(match.groups.color.length).trim(), }; } return null; }; const extractStartNamedColor = (source) => { const match = source.match(START_NAMED_COLOR_REGEX); if (match && match.groups) { return { color: match.groups.color, source: source.substring(match.groups.color.length, source.length).trim(), }; } return null; }; const extractColor = (source) => { const hexResult = extractStartWithHex(source); if (hexResult) { return hexResult; } const functionResult = extractStartWithFunction(source); if (functionResult) { return { color: functionResult.function, source: functionResult.source, }; } const colorResult = extractStartNamedColor(source); if (colorResult) { return colorResult; } return null; }; const angleToDeg = (angle, unit) => { switch (unit) { case 'deg': return angle; case 'turn': return angle * 360; case 'grad': return angle * 0.9; case 'rad': return (angle * 180) / Math.PI; } }; const removeCSSComments = (source) => { let start = source.indexOf('/*'); while (start >= 0) { const end = source.indexOf('*/', start + 2); if (end < 0) { break; } source = source.substring(0, start) + source.substring(end + 2, source.length); start = source.indexOf('/*'); } return source; }; const isLinearGradientWithAngle = (gradient) => gradient != null && 'angle' in gradient; const isLinearGradientWithSideOrCorner = (gradient) => gradient != null && 'sideOrCorner' in gradient; const isLinearGradientWithInterpolation = (gradient) => gradient != null && 'interpolation' in gradient; exports.START_WITH_INTERPOLATION = START_WITH_INTERPOLATION; exports.START_WITH_SIDE_OR_CORNER_REGEX = START_WITH_SIDE_OR_CORNER_REGEX; exports.angleToDeg = angleToDeg; exports.extractColor = extractColor; exports.extractStartComma = extractStartComma; exports.extractStartValueWithUnit = extractStartValueWithUnit; exports.isAngleUnit = isAngleUnit; exports.isLinearGradientWithAngle = isLinearGradientWithAngle; exports.isLinearGradientWithInterpolation = isLinearGradientWithInterpolation; exports.isLinearGradientWithSideOrCorner = isLinearGradientWithSideOrCorner; exports.removeCSSComments = removeCSSComments;