🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

gradient-parser

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gradient-parser - npm Package Compare versions

Comparing version

to
1.1.0

.github/workflows/ci.yml

108

build/node.js

@@ -109,2 +109,14 @@ // Copyright (c) 2014 Rafael Caricio. All rights reserved.

'visit_hsl': function(node) {
return visitor.visit_color('hsl(' + node.value[0] + ', ' + node.value[1] + '%, ' + node.value[2] + '%)', node);
},
'visit_hsla': function(node) {
return visitor.visit_color('hsla(' + node.value[0] + ', ' + node.value[1] + '%, ' + node.value[2] + '%, ' + node.value[3] + ')', node);
},
'visit_var': function(node) {
return visitor.visit_color('var(' + node.value + ')', node);
},
'visit_color': function(resultColor, node) {

@@ -142,2 +154,9 @@ var result = resultColor,

'visit_object': function(obj) {
if (obj.width && obj.height) {
return visitor.visit(obj.width) + ' ' + visitor.visit(obj.height);
}
return '';
},
'visit': function(element) {

@@ -151,2 +170,4 @@ if (!element) {

return visitor.visit_array(element, result);
} else if (typeof element === 'object' && !element.type) {
return visitor.visit_object(element);
} else if (element.type) {

@@ -184,3 +205,3 @@ var nodeVisitor = visitor['visit_' + element.type];

repeatingRadialGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/i,
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|top (left|right)|bottom (left|right)|left|right|top|bottom)/i,
extentKeywords: /^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,

@@ -192,2 +213,3 @@ positionKeywords: /^(left|center|right|top|bottom)/i,

angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
radianValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))rad/,
startCall: /^\(/,

@@ -200,3 +222,7 @@ endCall: /^\)/,

rgbaColor: /^rgba/i,
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/
varColor: /^var/i,
variableName: /^(--[a-zA-Z0-9-,\s\#]+)/,
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/,
hslColor: /^hsl/i,
hslaColor: /^hsla/i,
};

@@ -294,3 +320,4 @@

function matchAngle() {
return match('angular', tokens.angleValue, 1);
return match('angular', tokens.angleValue, 1) ||
match('angular', tokens.radianValue, 1);
}

@@ -363,3 +390,3 @@

if (ellipse) {
ellipse.style = matchDistance() || matchExtentKeyword();
ellipse.style = matchPositioning() || matchDistance() || matchExtentKeyword();
}

@@ -436,4 +463,7 @@

return matchHexColor() ||
matchHSLAColor() ||
matchHSLColor() ||
matchRGBAColor() ||
matchRGBColor() ||
matchVarColor() ||
matchLiteralColor();

@@ -468,2 +498,66 @@ }

function matchVarColor() {
return matchCall(tokens.varColor, function () {
return {
type: 'var',
value: matchVariableName()
};
});
}
function matchHSLColor() {
return matchCall(tokens.hslColor, function() {
// Check for percentage before trying to parse the hue
var lookahead = scan(tokens.percentageValue);
if (lookahead) {
error('HSL hue value must be a number in degrees (0-360) or normalized (-360 to 360), not a percentage');
}
var hue = matchNumber();
scan(tokens.comma);
var captures = scan(tokens.percentageValue);
var sat = captures ? captures[1] : null;
scan(tokens.comma);
captures = scan(tokens.percentageValue);
var light = captures ? captures[1] : null;
if (!sat || !light) {
error('Expected percentage value for saturation and lightness in HSL');
}
return {
type: 'hsl',
value: [hue, sat, light]
};
});
}
function matchHSLAColor() {
return matchCall(tokens.hslaColor, function() {
var hue = matchNumber();
scan(tokens.comma);
var captures = scan(tokens.percentageValue);
var sat = captures ? captures[1] : null;
scan(tokens.comma);
captures = scan(tokens.percentageValue);
var light = captures ? captures[1] : null;
scan(tokens.comma);
var alpha = matchNumber();
if (!sat || !light) {
error('Expected percentage value for saturation and lightness in HSLA');
}
return {
type: 'hsla',
value: [hue, sat, light, alpha]
};
});
}
function matchPercentage() {
var captures = scan(tokens.percentageValue);
return captures ? captures[1] : null;
}
function matchVariableName() {
return scan(tokens.variableName)[1];
}
function matchNumber() {

@@ -520,3 +614,7 @@ return scan(tokens.number)[1];

return function(code) {
input = code.toString();
input = code.toString().trim();
// Remove trailing semicolon if present
if (input.endsWith(';')) {
input = input.slice(0, -1);
}
return getAST();

@@ -523,0 +621,0 @@ };

@@ -16,3 +16,3 @@ var GradientParser = (window.GradientParser || {});

repeatingRadialGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/i,
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|top (left|right)|bottom (left|right)|left|right|top|bottom)/i,
extentKeywords: /^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,

@@ -24,2 +24,3 @@ positionKeywords: /^(left|center|right|top|bottom)/i,

angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
radianValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))rad/,
startCall: /^\(/,

@@ -32,3 +33,7 @@ endCall: /^\)/,

rgbaColor: /^rgba/i,
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/
varColor: /^var/i,
variableName: /^(--[a-zA-Z0-9-,\s\#]+)/,
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/,
hslColor: /^hsl/i,
hslaColor: /^hsla/i,
};

@@ -126,3 +131,4 @@

function matchAngle() {
return match('angular', tokens.angleValue, 1);
return match('angular', tokens.angleValue, 1) ||
match('angular', tokens.radianValue, 1);
}

@@ -195,3 +201,3 @@

if (ellipse) {
ellipse.style = matchDistance() || matchExtentKeyword();
ellipse.style = matchPositioning() || matchDistance() || matchExtentKeyword();
}

@@ -268,4 +274,7 @@

return matchHexColor() ||
matchHSLAColor() ||
matchHSLColor() ||
matchRGBAColor() ||
matchRGBColor() ||
matchVarColor() ||
matchLiteralColor();

@@ -300,2 +309,66 @@ }

function matchVarColor() {
return matchCall(tokens.varColor, function () {
return {
type: 'var',
value: matchVariableName()
};
});
}
function matchHSLColor() {
return matchCall(tokens.hslColor, function() {
// Check for percentage before trying to parse the hue
var lookahead = scan(tokens.percentageValue);
if (lookahead) {
error('HSL hue value must be a number in degrees (0-360) or normalized (-360 to 360), not a percentage');
}
var hue = matchNumber();
scan(tokens.comma);
var captures = scan(tokens.percentageValue);
var sat = captures ? captures[1] : null;
scan(tokens.comma);
captures = scan(tokens.percentageValue);
var light = captures ? captures[1] : null;
if (!sat || !light) {
error('Expected percentage value for saturation and lightness in HSL');
}
return {
type: 'hsl',
value: [hue, sat, light]
};
});
}
function matchHSLAColor() {
return matchCall(tokens.hslaColor, function() {
var hue = matchNumber();
scan(tokens.comma);
var captures = scan(tokens.percentageValue);
var sat = captures ? captures[1] : null;
scan(tokens.comma);
captures = scan(tokens.percentageValue);
var light = captures ? captures[1] : null;
scan(tokens.comma);
var alpha = matchNumber();
if (!sat || !light) {
error('Expected percentage value for saturation and lightness in HSLA');
}
return {
type: 'hsla',
value: [hue, sat, light, alpha]
};
});
}
function matchPercentage() {
var captures = scan(tokens.percentageValue);
return captures ? captures[1] : null;
}
function matchVariableName() {
return scan(tokens.variableName)[1];
}
function matchNumber() {

@@ -352,3 +425,7 @@ return scan(tokens.number)[1];

return function(code) {
input = code.toString();
input = code.toString().trim();
// Remove trailing semicolon if present
if (input.endsWith(';')) {
input = input.slice(0, -1);
}
return getAST();

@@ -466,2 +543,14 @@ };

'visit_hsl': function(node) {
return visitor.visit_color('hsl(' + node.value[0] + ', ' + node.value[1] + '%, ' + node.value[2] + '%)', node);
},
'visit_hsla': function(node) {
return visitor.visit_color('hsla(' + node.value[0] + ', ' + node.value[1] + '%, ' + node.value[2] + '%, ' + node.value[3] + ')', node);
},
'visit_var': function(node) {
return visitor.visit_color('var(' + node.value + ')', node);
},
'visit_color': function(resultColor, node) {

@@ -499,2 +588,9 @@ var result = resultColor,

'visit_object': function(obj) {
if (obj.width && obj.height) {
return visitor.visit(obj.width) + ' ' + visitor.visit(obj.height);
}
return '';
},
'visit': function(element) {

@@ -508,2 +604,4 @@ if (!element) {

return visitor.visit_array(element, result);
} else if (typeof element === 'object' && !element.type) {
return visitor.visit_object(element);
} else if (element.type) {

@@ -510,0 +608,0 @@ var nodeVisitor = visitor['visit_' + element.type];

@@ -14,3 +14,3 @@ // Copyright (c) 2014 Rafael Caricio. All rights reserved.

repeatingRadialGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/i,
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|top (left|right)|bottom (left|right)|left|right|top|bottom)/i,
extentKeywords: /^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,

@@ -22,2 +22,3 @@ positionKeywords: /^(left|center|right|top|bottom)/i,

angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
radianValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))rad/,
startCall: /^\(/,

@@ -30,3 +31,7 @@ endCall: /^\)/,

rgbaColor: /^rgba/i,
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/
varColor: /^var/i,
variableName: /^(--[a-zA-Z0-9-,\s\#]+)/,
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/,
hslColor: /^hsl/i,
hslaColor: /^hsla/i,
};

@@ -124,3 +129,4 @@

function matchAngle() {
return match('angular', tokens.angleValue, 1);
return match('angular', tokens.angleValue, 1) ||
match('angular', tokens.radianValue, 1);
}

@@ -193,3 +199,3 @@

if (ellipse) {
ellipse.style = matchDistance() || matchExtentKeyword();
ellipse.style = matchPositioning() || matchDistance() || matchExtentKeyword();
}

@@ -266,4 +272,7 @@

return matchHexColor() ||
matchHSLAColor() ||
matchHSLColor() ||
matchRGBAColor() ||
matchRGBColor() ||
matchVarColor() ||
matchLiteralColor();

@@ -298,2 +307,66 @@ }

function matchVarColor() {
return matchCall(tokens.varColor, function () {
return {
type: 'var',
value: matchVariableName()
};
});
}
function matchHSLColor() {
return matchCall(tokens.hslColor, function() {
// Check for percentage before trying to parse the hue
var lookahead = scan(tokens.percentageValue);
if (lookahead) {
error('HSL hue value must be a number in degrees (0-360) or normalized (-360 to 360), not a percentage');
}
var hue = matchNumber();
scan(tokens.comma);
var captures = scan(tokens.percentageValue);
var sat = captures ? captures[1] : null;
scan(tokens.comma);
captures = scan(tokens.percentageValue);
var light = captures ? captures[1] : null;
if (!sat || !light) {
error('Expected percentage value for saturation and lightness in HSL');
}
return {
type: 'hsl',
value: [hue, sat, light]
};
});
}
function matchHSLAColor() {
return matchCall(tokens.hslaColor, function() {
var hue = matchNumber();
scan(tokens.comma);
var captures = scan(tokens.percentageValue);
var sat = captures ? captures[1] : null;
scan(tokens.comma);
captures = scan(tokens.percentageValue);
var light = captures ? captures[1] : null;
scan(tokens.comma);
var alpha = matchNumber();
if (!sat || !light) {
error('Expected percentage value for saturation and lightness in HSLA');
}
return {
type: 'hsla',
value: [hue, sat, light, alpha]
};
});
}
function matchPercentage() {
var captures = scan(tokens.percentageValue);
return captures ? captures[1] : null;
}
function matchVariableName() {
return scan(tokens.variableName)[1];
}
function matchNumber() {

@@ -350,5 +423,9 @@ return scan(tokens.number)[1];

return function(code) {
input = code.toString();
input = code.toString().trim();
// Remove trailing semicolon if present
if (input.endsWith(';')) {
input = input.slice(0, -1);
}
return getAST();
};
})();

@@ -109,2 +109,14 @@ // Copyright (c) 2014 Rafael Caricio. All rights reserved.

'visit_hsl': function(node) {
return visitor.visit_color('hsl(' + node.value[0] + ', ' + node.value[1] + '%, ' + node.value[2] + '%)', node);
},
'visit_hsla': function(node) {
return visitor.visit_color('hsla(' + node.value[0] + ', ' + node.value[1] + '%, ' + node.value[2] + '%, ' + node.value[3] + ')', node);
},
'visit_var': function(node) {
return visitor.visit_color('var(' + node.value + ')', node);
},
'visit_color': function(resultColor, node) {

@@ -142,2 +154,9 @@ var result = resultColor,

'visit_object': function(obj) {
if (obj.width && obj.height) {
return visitor.visit(obj.width) + ' ' + visitor.visit(obj.height);
}
return '';
},
'visit': function(element) {

@@ -151,2 +170,4 @@ if (!element) {

return visitor.visit_array(element, result);
} else if (typeof element === 'object' && !element.type) {
return visitor.visit_object(element);
} else if (element.type) {

@@ -153,0 +174,0 @@ var nodeVisitor = visitor['visit_' + element.type];

21

package.json
{
"name": "gradient-parser",
"version": "1.0.2",
"version": "1.1.0",
"description": "Parse CSS3 gradient definitions and return an AST.",

@@ -28,3 +28,9 @@ "author": {

"scripts": {
"test": "grunt"
"test": "mocha spec/**/*.js",
"build": "node build.js",
"build:node": "node build.js --node",
"build:web": "node build.js --web",
"build:minify": "node build.js --minify",
"start": "python -m SimpleHTTPServer 3000",
"prepublish": "npm run build"
},

@@ -37,10 +43,5 @@ "keywords": [

"devDependencies": {
"expect.js": "*",
"grunt": "*",
"grunt-browserify": "^3.0.1",
"grunt-complexity": "*",
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-uglify": "^0.5.1",
"grunt-mocha-test": "^0.11.0",
"mocha": "*"
"expect.js": "^0.3.1",
"esbuild": "^0.20.2",
"mocha": "^10.3.0"
},

@@ -47,0 +48,0 @@ "engines": {

# Gradient Parser
[![npm version](https://badge.fury.io/js/gradient-parser.svg)](https://badge.fury.io/js/gradient-parser)
## About

@@ -39,6 +41,66 @@

## Install Choices
- `bower install gradient-parser`
- [download the zip](https://github.com/rafaelcaricio/gradient-parser/archive/master.zip)
## Installation
Install via npm:
```bash
npm install gradient-parser
```
Import in Node.js:
```javascript
const gradient = require('gradient-parser');
```
For browser usage:
```html
<script src="node_modules/gradient-parser/build/web.js"></script>
```
Or [download the zip](https://github.com/rafaelcaricio/gradient-parser/archive/master.zip)
## Development
### Project Status
Gradient-parser has been modernized (as of v1.1.0):
- Removed Bower support in favor of npm exclusively
- Replaced Grunt with a modern build system using esbuild
- Added minification support
- Updated dependencies to specific versions
- Improved npm scripts for better developer experience
### Build
Gradient-parser uses a modern build system with esbuild for building and minification.
```bash
# Build both Node.js and web bundles
npm run build
# Build only Node.js bundle
npm run build:node
# Build only web bundle
npm run build:web
# Build minified bundles
npm run build:minify
```
### Testing
Run the test suite with:
```bash
npm test
```
### Starting a local server
You can run a simple HTTP server for development:
```bash
npm start
```
## API

@@ -134,3 +196,3 @@

Copyright (c) 2014 Rafael Caricio rafael@caricio.com
Copyright (c) 2014-2025 Rafael Caricio rafael@caricio.com

@@ -137,0 +199,0 @@ Permission is hereby granted, free of charge, to any person obtaining

@@ -137,3 +137,8 @@ 'use strict';

{type: 'angular', unparsedValue: '-145deg', value: '-145'},
{type: 'directional', unparsedValue: 'to left top', value: 'left top'}
{type: 'angular', unparsedValue: '1rad', value: '1'},
{type: 'directional', unparsedValue: 'to left top', value: 'left top'},
{type: 'directional', unparsedValue: 'to top left', value: 'top left'},
{type: 'directional', unparsedValue: 'to top right', value: 'top right'},
{type: 'directional', unparsedValue: 'to bottom left', value: 'bottom left'},
{type: 'directional', unparsedValue: 'to bottom right', value: 'bottom right'}
].forEach(function(orientation) {

@@ -159,3 +164,7 @@ describe('parse orientation ' + orientation.type, function() {

{type: 'rgb', unparsedValue: 'rgb(243, 226, 195)', value: ['243', '226', '195']},
{type: 'rgba', unparsedValue: 'rgba(243, 226, 195)', value: ['243', '226', '195']}
{type: 'rgba', unparsedValue: 'rgba(243, 226, 195)', value: ['243', '226', '195']},
{type: 'hsl', unparsedValue: 'hsl(120, 60%, 70%)', value: ['120', '60', '70']},
{type: 'hsla', unparsedValue: 'hsla(120, 60%, 70%, 0.3)', value: ['120', '60', '70', '0.3']},
{type: 'hsla', unparsedValue: 'hsla(240, 100%, 50%, 0.5)', value: ['240', '100', '50', '0.5']},
{type: 'var', unparsedValue: 'var(--color-red)', value: '--color-red'},
].forEach(function(color) {

@@ -174,2 +183,22 @@ describe('parse color type '+ color.type, function() {

});
describe('error cases for HSL/HSLA', function() {
it('should error on missing percentage for saturation', function() {
expect(function() {
gradients.parse('linear-gradient(hsl(120, 60, 70%))');
}).to.throwException(/Expected percentage value/);
});
it('should error on missing percentage for lightness', function() {
expect(function() {
gradients.parse('linear-gradient(hsl(120, 60%, 70))');
}).to.throwException(/Expected percentage value/);
});
it('should error on percentage for hue', function() {
expect(function() {
gradients.parse('linear-gradient(hsl(120%, 60%, 70%))');
}).to.throwException(/HSL hue value must be a number in degrees \(0-360\) or normalized \(-360 to 360\), not a percentage/);
});
});
});

@@ -214,4 +243,143 @@

});
it('should parse ellipse with dimensions and position', function() {
const gradient = 'repeating-radial-gradient(ellipse 40px 134px at 50% 96%, rgb(0, 165, 223) 0%, rgb(62, 20, 123) 6.6%)';
const ast = gradients.parse(gradient);
expect(ast[0].type).to.equal('repeating-radial-gradient');
expect(ast[0].orientation[0].type).to.equal('shape');
expect(ast[0].orientation[0].value).to.equal('ellipse');
// Check the style (size dimensions)
expect(ast[0].orientation[0].style.type).to.equal('position');
expect(ast[0].orientation[0].style.value.x.type).to.equal('px');
expect(ast[0].orientation[0].style.value.x.value).to.equal('40');
expect(ast[0].orientation[0].style.value.y.type).to.equal('px');
expect(ast[0].orientation[0].style.value.y.value).to.equal('134');
// Check the position
expect(ast[0].orientation[0].at.type).to.equal('position');
expect(ast[0].orientation[0].at.value.x.type).to.equal('%');
expect(ast[0].orientation[0].at.value.x.value).to.equal('50');
expect(ast[0].orientation[0].at.value.y.type).to.equal('%');
expect(ast[0].orientation[0].at.value.y.value).to.equal('96');
// Check the color stops
expect(ast[0].colorStops).to.have.length(2);
expect(ast[0].colorStops[0].type).to.equal('rgb');
expect(ast[0].colorStops[0].value).to.eql(['0', '165', '223']);
expect(ast[0].colorStops[0].length.type).to.equal('%');
expect(ast[0].colorStops[0].length.value).to.equal('0');
expect(ast[0].colorStops[1].type).to.equal('rgb');
expect(ast[0].colorStops[1].value).to.eql(['62', '20', '123']);
expect(ast[0].colorStops[1].length.type).to.equal('%');
expect(ast[0].colorStops[1].length.value).to.equal('6.6');
});
it('should parse full Pride flag gradient', function() {
const gradient = 'repeating-radial-gradient(ellipse 40px 134px at 50% 96%,rgb(0, 165, 223) 0%,rgb(62, 20, 123) 6.6%,rgb(226, 0, 121) 13.2%,rgb(223, 19, 44) 18.8%,rgb(243, 239, 21) 24.1%,rgb(0, 152, 71) 33.3%)';
const ast = gradients.parse(gradient);
expect(ast[0].type).to.equal('repeating-radial-gradient');
expect(ast[0].orientation[0].type).to.equal('shape');
expect(ast[0].orientation[0].value).to.equal('ellipse');
// Check dimensions and position
expect(ast[0].orientation[0].style.type).to.equal('position');
expect(ast[0].orientation[0].at.type).to.equal('position');
// Verify all color stops are present (Pride flag colors)
expect(ast[0].colorStops).to.have.length(6);
// Check the first and last color stops
expect(ast[0].colorStops[0].type).to.equal('rgb');
expect(ast[0].colorStops[0].value).to.eql(['0', '165', '223']);
expect(ast[0].colorStops[5].type).to.equal('rgb');
expect(ast[0].colorStops[5].value).to.eql(['0', '152', '71']);
expect(ast[0].colorStops[5].length.type).to.equal('%');
expect(ast[0].colorStops[5].length.value).to.equal('33.3');
});
});
describe('parse gradient strings with trailing semicolons', function() {
it('should parse linear-gradient with trailing semicolon', function() {
const inputWithSemicolon = 'linear-gradient(red, blue);';
const ast = gradients.parse(inputWithSemicolon);
expect(ast[0].type).to.equal('linear-gradient');
expect(ast[0].colorStops).to.have.length(2);
expect(ast[0].colorStops[0].value).to.equal('red');
expect(ast[0].colorStops[1].value).to.equal('blue');
});
it('should parse radial-gradient with trailing semicolon', function() {
const inputWithSemicolon = 'radial-gradient(circle, red, blue);';
const ast = gradients.parse(inputWithSemicolon);
expect(ast[0].type).to.equal('radial-gradient');
expect(ast[0].colorStops).to.have.length(2);
expect(ast[0].colorStops[0].value).to.equal('red');
expect(ast[0].colorStops[1].value).to.equal('blue');
});
it('should parse complex gradient with trailing semicolon', function() {
const inputWithSemicolon = 'linear-gradient(to right, rgb(22, 234, 174) 0%, rgb(126, 32, 207) 100%);';
const ast = gradients.parse(inputWithSemicolon);
expect(ast[0].type).to.equal('linear-gradient');
expect(ast[0].orientation.type).to.equal('directional');
expect(ast[0].orientation.value).to.equal('right');
expect(ast[0].colorStops).to.have.length(2);
expect(ast[0].colorStops[0].type).to.equal('rgb');
expect(ast[0].colorStops[0].length.type).to.equal('%');
expect(ast[0].colorStops[0].length.value).to.equal('0');
expect(ast[0].colorStops[1].type).to.equal('rgb');
expect(ast[0].colorStops[1].length.type).to.equal('%');
expect(ast[0].colorStops[1].length.value).to.equal('100');
});
});
describe('parse gradient strings', function() {
it('should parse repeating linear gradient with bottom right direction', function() {
const gradient = 'repeating-linear-gradient(to bottom right,rgb(254, 158, 150) 0%,rgb(172, 79, 115) 100%)';
const ast = gradients.parse(gradient);
expect(ast[0].type).to.equal('repeating-linear-gradient');
expect(ast[0].orientation.type).to.equal('directional');
expect(ast[0].orientation.value).to.equal('bottom right');
expect(ast[0].colorStops).to.have.length(2);
expect(ast[0].colorStops[0].type).to.equal('rgb');
expect(ast[0].colorStops[0].value).to.eql(['254', '158', '150']);
expect(ast[0].colorStops[0].length.type).to.equal('%');
expect(ast[0].colorStops[0].length.value).to.equal('0');
expect(ast[0].colorStops[1].type).to.equal('rgb');
expect(ast[0].colorStops[1].value).to.eql(['172', '79', '115']);
expect(ast[0].colorStops[1].length.type).to.equal('%');
expect(ast[0].colorStops[1].length.value).to.equal('100');
});
describe('parse different color formats', function() {
const testGradients = [
'linear-gradient(red, blue)',
'linear-gradient(red, #00f)',
'linear-gradient(red, #0000ff)',
'linear-gradient(red, rgb(0, 0, 255))',
'linear-gradient(red, rgba(0, 0, 255, 1))',
'linear-gradient(red, hsl(240, 50%, 100%))',
'linear-gradient(red, hsla(240, 50%, 100%, 1))'
];
testGradients.forEach(function(gradient) {
it('should parse ' + gradient, function() {
const result = gradients.parse(gradient);
expect(result[0].type).to.equal('linear-gradient');
expect(result[0].colorStops).to.have.length(2);
expect(result[0].colorStops[0].type).to.equal('literal');
expect(result[0].colorStops[0].value).to.equal('red');
});
});
});
});
});

@@ -33,2 +33,7 @@ 'use strict';

it('should serialize gradient with var', function() {
var gradientDef = 'linear-gradient(var(--color-black), white)';
expect(gradients.stringify(gradients.parse(gradientDef))).to.equal(gradientDef);
});
it('should serialize gradient with rgb', function() {

@@ -35,0 +40,0 @@ var gradientDef = 'linear-gradient(rgb(1, 2, 3), white)';