UNPKG

gradient-utils

Version:
204 lines (200 loc) 6.67 kB
'use strict'; var utils = require('../utils-HrBEEUzj.js'); const linearPrefix = 'linear-gradient('; const repeatingPrefix = 'repeating-linear-gradient('; const parseLinearGradient = (gradient) => linearGradientParser(gradient, linearPrefix); const parseRepeatingLinearGradient = (gradient) => linearGradientParser(gradient, repeatingPrefix, true); const linearGradientParser = (gradient, prefix, repeatable = false) => { if (!gradient) { return null; } gradient = utils.removeCSSComments(gradient).toLowerCase(); //fix the casting toLowerCase. Otherwise, we can lose currentColor or should do insensitivity search every time gradient = gradient.replaceAll('currentcolor', 'currentColor'); gradient = gradient.trim(); if (!gradient.startsWith(prefix) || !gradient.endsWith(')')) { return null; } gradient = gradient.substring(prefix.length, gradient.length - 1).trim(); const extractAngleResult = extractAngle(gradient); if (!extractAngleResult) { return null; } let linearGradient; if ('angle' in extractAngleResult) { linearGradient = { angle: extractAngleResult.angle, colorStops: [], }; } else if ('sideOrCorner' in extractAngleResult) { linearGradient = { sideOrCorner: extractAngleResult.sideOrCorner, colorStops: [], }; } else { linearGradient = { interpolation: extractAngleResult.interpolation, colorStops: [], }; } gradient = extractAngleResult.gradientWithoutAngle; const colorStops = parseColorStops(gradient); if (!colorStops) { return null; } linearGradient.colorStops = colorStops; if (repeatable) { linearGradient.repeatable = true; } return linearGradient; }; const extractAngle = (gradient) => { const unit = 'deg'; let degAngle = 180; let sourceValue = ''; const angleUnit = utils.extractStartValueWithUnit(gradient, unit); if (angleUnit && utils.isAngleUnit(angleUnit.unit)) { degAngle = utils.angleToDeg(angleUnit.value, angleUnit.unit); sourceValue = angleUnit.sourceValue; const gradientWithoutAngle = utils.extractStartComma(angleUnit.source); if (gradientWithoutAngle == null) { return null; } return { angle: { unit: angleUnit.unit, degAngle, sourceValue, }, gradientWithoutAngle, }; } const sideOrCorner = extractSideOrCorner(gradient); if (sideOrCorner) { return { sideOrCorner: { top: sideOrCorner.top, bottom: sideOrCorner.bottom, left: sideOrCorner.left, right: sideOrCorner.right, sourceValue: sideOrCorner.sourceValue, }, gradientWithoutAngle: sideOrCorner.gradientWithoutAngle, }; } const interpolation = extractInterpolation(gradient); if (interpolation) { return interpolation; } return { angle: { unit, degAngle, sourceValue, }, gradientWithoutAngle: gradient, }; }; const extractSideOrCorner = (source) => { const match = source.match(utils.START_WITH_SIDE_OR_CORNER_REGEX); if (match) { const sourceValue = match[0]; const top = sourceValue.includes('top'); const bottom = sourceValue.includes('bottom'); const left = sourceValue.includes('left'); const right = sourceValue.includes('right'); const gradientWithoutAngle = utils.extractStartComma(source.substring(sourceValue.length)); if (gradientWithoutAngle == null) { return null; } return { top, bottom, left, right, sourceValue, gradientWithoutAngle, }; } return null; }; const extractInterpolation = (source) => { const match = source.match(utils.START_WITH_INTERPOLATION); if (match && match.groups) { return { interpolation: match.groups.interpolation, gradientWithoutAngle: source.substring(match[0].length).trim(), }; } return null; }; const parseColorStop = (source) => { let colorStop = null; const colorResult = utils.extractColor(source); if (colorResult) { source = colorResult.source; colorStop = { color: colorResult.color, alpha: colorResult.alpha, }; } let valueWithUnit = utils.extractStartValueWithUnit(source); if (valueWithUnit) { source = valueWithUnit.source; if (!colorStop && valueWithUnit.unit === '%') { colorStop = { value: valueWithUnit.value, unit: '%', sourceValue: valueWithUnit.sourceValue, }; } else if (colorStop) { colorStop.start = { value: valueWithUnit.value, unit: valueWithUnit.unit, sourceValue: valueWithUnit.sourceValue, }; } } valueWithUnit = utils.extractStartValueWithUnit(source); if (valueWithUnit && colorStop && 'color' in colorStop) { colorStop.end = { value: valueWithUnit.value, unit: valueWithUnit.unit, sourceValue: valueWithUnit.sourceValue, }; } return colorStop; }; const parseColorStops = (source) => { const result = []; let i = 0; let bracesCount = 0; while (i < source.length) { if (source.charAt(i) === '(') { bracesCount++; } if (source.charAt(i) === ')') { bracesCount--; } const comma = source.charAt(i) === ','; if ((comma || i === source.length - 1) && bracesCount === 0) { const colorStop = parseColorStop(source.substring(0, comma ? i : i + 1).trim()); if (colorStop === null) { return null; } result.push(colorStop); source = source.substring(i + 1, source.length).trim(); i = 0; } i++; } return result; }; exports.isLinearGradientWithAngle = utils.isLinearGradientWithAngle; exports.isLinearGradientWithInterpolation = utils.isLinearGradientWithInterpolation; exports.isLinearGradientWithSideOrCorner = utils.isLinearGradientWithSideOrCorner; exports.parseLinearGradient = parseLinearGradient; exports.parseRepeatingLinearGradient = parseRepeatingLinearGradient;