Compare commits
27 commits
Author | SHA1 | Date | |
---|---|---|---|
Rafael Caricio | 92b6e8011e | ||
a3494b3421 | |||
330ffa92cd | |||
Rafael Caricio | cce801d1df | ||
Rafael Caricio | eff630c873 | ||
Rafael Caricio | c4ba2836b6 | ||
Rafael Caricio | 015088b929 | ||
4bfe95a98f | |||
Rafael Caricio | 04708dcb45 | ||
Rafael Caricio | 2720da021f | ||
12648a2a28 | |||
Rafael Caricio | 4b49f43244 | ||
d0e6c24616 | |||
ac093b15b3 | |||
3559c23b44 | |||
37e8f70262 | |||
129101533e | |||
75e01de8e4 | |||
77a461fc4d | |||
cb2e9e03f6 | |||
6c57770890 | |||
8675ce856f | |||
b61d2420c7 | |||
74b73132bc | |||
ce4521b1b3 | |||
f3de5fc9b6 | |||
4084ba4b5c |
16
bower.json
16
bower.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "gradient-parser",
|
||||
"version": "0.1.0",
|
||||
"main": "index.js",
|
||||
"version": "1.0.0",
|
||||
"main": "build/web.js",
|
||||
"ignore": [
|
||||
".editorconfig",
|
||||
".gitattributes",
|
||||
|
@ -10,9 +10,15 @@
|
|||
".npmignore",
|
||||
".travis.yml",
|
||||
".umd",
|
||||
"gulpfile.js",
|
||||
"npm-shrinkwrap.json",
|
||||
"package.json"
|
||||
"package.json",
|
||||
"index.html",
|
||||
"Makefile",
|
||||
"build/node.js",
|
||||
"README.md",
|
||||
"*.js",
|
||||
"lib/*",
|
||||
"spec/*",
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
|
||||
|
|
516
build/node.js
Normal file
516
build/node.js
Normal file
|
@ -0,0 +1,516 @@
|
|||
// Copyright (c) 2014 Rafael Caricio. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var GradientParser = (GradientParser || {});
|
||||
|
||||
GradientParser.stringify = (function() {
|
||||
|
||||
var visitor = {
|
||||
|
||||
'visit_linear-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_repeating-linear-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_radial-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_repeating-radial-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_gradient': function(node) {
|
||||
var orientation = visitor.visit(node.orientation);
|
||||
if (orientation) {
|
||||
orientation += ', ';
|
||||
}
|
||||
|
||||
return node.type + '(' + orientation + visitor.visit(node.colorStops) + ')';
|
||||
},
|
||||
|
||||
'visit_shape': function(node) {
|
||||
var result = node.value,
|
||||
at = visitor.visit(node.at),
|
||||
style = visitor.visit(node.style);
|
||||
|
||||
if (style) {
|
||||
result += ' ' + style;
|
||||
}
|
||||
|
||||
if (at) {
|
||||
result += ' at ' + at;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_default-radial': function(node) {
|
||||
var result = '',
|
||||
at = visitor.visit(node.at);
|
||||
|
||||
if (at) {
|
||||
result += at;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_extent-keyword': function(node) {
|
||||
var result = node.value,
|
||||
at = visitor.visit(node.at);
|
||||
|
||||
if (at) {
|
||||
result += ' at ' + at;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_position-keyword': function(node) {
|
||||
return node.value;
|
||||
},
|
||||
|
||||
'visit_position': function(node) {
|
||||
return visitor.visit(node.value.x) + ' ' + visitor.visit(node.value.y);
|
||||
},
|
||||
|
||||
'visit_%': function(node) {
|
||||
return node.value + '%';
|
||||
},
|
||||
|
||||
'visit_em': function(node) {
|
||||
return node.value + 'em';
|
||||
},
|
||||
|
||||
'visit_px': function(node) {
|
||||
return node.value + 'px';
|
||||
},
|
||||
|
||||
'visit_literal': function(node) {
|
||||
return visitor.visit_color(node.value, node);
|
||||
},
|
||||
|
||||
'visit_hex': function(node) {
|
||||
return visitor.visit_color('#' + node.value, node);
|
||||
},
|
||||
|
||||
'visit_rgb': function(node) {
|
||||
return visitor.visit_color('rgb(' + node.value.join(', ') + ')', node);
|
||||
},
|
||||
|
||||
'visit_rgba': function(node) {
|
||||
return visitor.visit_color('rgba(' + node.value.join(', ') + ')', node);
|
||||
},
|
||||
|
||||
'visit_color': function(resultColor, node) {
|
||||
var result = resultColor,
|
||||
length = visitor.visit(node.length);
|
||||
|
||||
if (length) {
|
||||
result += ' ' + length;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_angular': function(node) {
|
||||
return node.value + 'deg';
|
||||
},
|
||||
|
||||
'visit_directional': function(node) {
|
||||
return 'to ' + node.value;
|
||||
},
|
||||
|
||||
'visit_array': function(elements) {
|
||||
var result = '',
|
||||
size = elements.length;
|
||||
|
||||
elements.forEach(function(element, i) {
|
||||
result += visitor.visit(element);
|
||||
if (i < size - 1) {
|
||||
result += ', ';
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit': function(element) {
|
||||
if (!element) {
|
||||
return '';
|
||||
}
|
||||
var result = '';
|
||||
|
||||
if (element instanceof Array) {
|
||||
return visitor.visit_array(element, result);
|
||||
} else if (element.type) {
|
||||
var nodeVisitor = visitor['visit_' + element.type];
|
||||
if (nodeVisitor) {
|
||||
return nodeVisitor(element);
|
||||
} else {
|
||||
throw Error('Missing visitor visit_' + element.type);
|
||||
}
|
||||
} else {
|
||||
throw Error('Invalid node.');
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return function(root) {
|
||||
return visitor.visit(root);
|
||||
};
|
||||
})();
|
||||
|
||||
// Copyright (c) 2014 Rafael Caricio. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var GradientParser = (GradientParser || {});
|
||||
|
||||
GradientParser.parse = (function() {
|
||||
|
||||
var tokens = {
|
||||
linearGradient: /^(\-(webkit|o|ms|moz)\-)?(linear\-gradient)/i,
|
||||
repeatingLinearGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-linear\-gradient)/i,
|
||||
radialGradient: /^(\-(webkit|o|ms|moz)\-)?(radial\-gradient)/i,
|
||||
repeatingRadialGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/i,
|
||||
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
|
||||
extentKeywords: /^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,
|
||||
positionKeywords: /^(left|center|right|top|bottom)/i,
|
||||
pixelValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))px/,
|
||||
percentageValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))\%/,
|
||||
emValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))em/,
|
||||
angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
|
||||
startCall: /^\(/,
|
||||
endCall: /^\)/,
|
||||
comma: /^,/,
|
||||
hexColor: /^\#([0-9a-fA-F]+)/,
|
||||
literalColor: /^([a-zA-Z]+)/,
|
||||
rgbColor: /^rgb/i,
|
||||
rgbaColor: /^rgba/i,
|
||||
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/
|
||||
};
|
||||
|
||||
var input = '';
|
||||
|
||||
function error(msg) {
|
||||
var err = new Error(input + ': ' + msg);
|
||||
err.source = input;
|
||||
throw err;
|
||||
}
|
||||
|
||||
function getAST() {
|
||||
var ast = matchListDefinitions();
|
||||
|
||||
if (input.length > 0) {
|
||||
error('Invalid input not EOF');
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
function matchListDefinitions() {
|
||||
return matchListing(matchDefinition);
|
||||
}
|
||||
|
||||
function matchDefinition() {
|
||||
return matchGradient(
|
||||
'linear-gradient',
|
||||
tokens.linearGradient,
|
||||
matchLinearOrientation) ||
|
||||
|
||||
matchGradient(
|
||||
'repeating-linear-gradient',
|
||||
tokens.repeatingLinearGradient,
|
||||
matchLinearOrientation) ||
|
||||
|
||||
matchGradient(
|
||||
'radial-gradient',
|
||||
tokens.radialGradient,
|
||||
matchListRadialOrientations) ||
|
||||
|
||||
matchGradient(
|
||||
'repeating-radial-gradient',
|
||||
tokens.repeatingRadialGradient,
|
||||
matchListRadialOrientations);
|
||||
}
|
||||
|
||||
function matchGradient(gradientType, pattern, orientationMatcher) {
|
||||
return matchCall(pattern, function(captures) {
|
||||
|
||||
var orientation = orientationMatcher();
|
||||
if (orientation) {
|
||||
if (!scan(tokens.comma)) {
|
||||
error('Missing comma before color stops');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: gradientType,
|
||||
orientation: orientation,
|
||||
colorStops: matchListing(matchColorStop)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchCall(pattern, callback) {
|
||||
var captures = scan(pattern);
|
||||
|
||||
if (captures) {
|
||||
if (!scan(tokens.startCall)) {
|
||||
error('Missing (');
|
||||
}
|
||||
|
||||
var result = callback(captures);
|
||||
|
||||
if (!scan(tokens.endCall)) {
|
||||
error('Missing )');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function matchLinearOrientation() {
|
||||
return matchSideOrCorner() ||
|
||||
matchAngle();
|
||||
}
|
||||
|
||||
function matchSideOrCorner() {
|
||||
return match('directional', tokens.sideOrCorner, 1);
|
||||
}
|
||||
|
||||
function matchAngle() {
|
||||
return match('angular', tokens.angleValue, 1);
|
||||
}
|
||||
|
||||
function matchListRadialOrientations() {
|
||||
var radialOrientations,
|
||||
radialOrientation = matchRadialOrientation(),
|
||||
lookaheadCache;
|
||||
|
||||
if (radialOrientation) {
|
||||
radialOrientations = [];
|
||||
radialOrientations.push(radialOrientation);
|
||||
|
||||
lookaheadCache = input;
|
||||
if (scan(tokens.comma)) {
|
||||
radialOrientation = matchRadialOrientation();
|
||||
if (radialOrientation) {
|
||||
radialOrientations.push(radialOrientation);
|
||||
} else {
|
||||
input = lookaheadCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return radialOrientations;
|
||||
}
|
||||
|
||||
function matchRadialOrientation() {
|
||||
var radialType = matchCircle() ||
|
||||
matchEllipse();
|
||||
|
||||
if (radialType) {
|
||||
radialType.at = matchAtPosition();
|
||||
} else {
|
||||
var extent = matchExtentKeyword();
|
||||
if (extent) {
|
||||
radialType = extent;
|
||||
var positionAt = matchAtPosition();
|
||||
if (positionAt) {
|
||||
radialType.at = positionAt;
|
||||
}
|
||||
} else {
|
||||
var defaultPosition = matchPositioning();
|
||||
if (defaultPosition) {
|
||||
radialType = {
|
||||
type: 'default-radial',
|
||||
at: defaultPosition
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return radialType;
|
||||
}
|
||||
|
||||
function matchCircle() {
|
||||
var circle = match('shape', /^(circle)/i, 0);
|
||||
|
||||
if (circle) {
|
||||
circle.style = matchLength() || matchExtentKeyword();
|
||||
}
|
||||
|
||||
return circle;
|
||||
}
|
||||
|
||||
function matchEllipse() {
|
||||
var ellipse = match('shape', /^(ellipse)/i, 0);
|
||||
|
||||
if (ellipse) {
|
||||
ellipse.style = matchDistance() || matchExtentKeyword();
|
||||
}
|
||||
|
||||
return ellipse;
|
||||
}
|
||||
|
||||
function matchExtentKeyword() {
|
||||
return match('extent-keyword', tokens.extentKeywords, 1);
|
||||
}
|
||||
|
||||
function matchAtPosition() {
|
||||
if (match('position', /^at/, 0)) {
|
||||
var positioning = matchPositioning();
|
||||
|
||||
if (!positioning) {
|
||||
error('Missing positioning value');
|
||||
}
|
||||
|
||||
return positioning;
|
||||
}
|
||||
}
|
||||
|
||||
function matchPositioning() {
|
||||
var location = matchCoordinates();
|
||||
|
||||
if (location.x || location.y) {
|
||||
return {
|
||||
type: 'position',
|
||||
value: location
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function matchCoordinates() {
|
||||
return {
|
||||
x: matchDistance(),
|
||||
y: matchDistance()
|
||||
};
|
||||
}
|
||||
|
||||
function matchListing(matcher) {
|
||||
var captures = matcher(),
|
||||
result = [];
|
||||
|
||||
if (captures) {
|
||||
result.push(captures);
|
||||
while (scan(tokens.comma)) {
|
||||
captures = matcher();
|
||||
if (captures) {
|
||||
result.push(captures);
|
||||
} else {
|
||||
error('One extra comma');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function matchColorStop() {
|
||||
var color = matchColor();
|
||||
|
||||
if (!color) {
|
||||
error('Expected color definition');
|
||||
}
|
||||
|
||||
color.length = matchDistance();
|
||||
return color;
|
||||
}
|
||||
|
||||
function matchColor() {
|
||||
return matchHexColor() ||
|
||||
matchRGBAColor() ||
|
||||
matchRGBColor() ||
|
||||
matchLiteralColor();
|
||||
}
|
||||
|
||||
function matchLiteralColor() {
|
||||
return match('literal', tokens.literalColor, 0);
|
||||
}
|
||||
|
||||
function matchHexColor() {
|
||||
return match('hex', tokens.hexColor, 1);
|
||||
}
|
||||
|
||||
function matchRGBColor() {
|
||||
return matchCall(tokens.rgbColor, function() {
|
||||
return {
|
||||
type: 'rgb',
|
||||
value: matchListing(matchNumber)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchRGBAColor() {
|
||||
return matchCall(tokens.rgbaColor, function() {
|
||||
return {
|
||||
type: 'rgba',
|
||||
value: matchListing(matchNumber)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchNumber() {
|
||||
return scan(tokens.number)[1];
|
||||
}
|
||||
|
||||
function matchDistance() {
|
||||
return match('%', tokens.percentageValue, 1) ||
|
||||
matchPositionKeyword() ||
|
||||
matchLength();
|
||||
}
|
||||
|
||||
function matchPositionKeyword() {
|
||||
return match('position-keyword', tokens.positionKeywords, 1);
|
||||
}
|
||||
|
||||
function matchLength() {
|
||||
return match('px', tokens.pixelValue, 1) ||
|
||||
match('em', tokens.emValue, 1);
|
||||
}
|
||||
|
||||
function match(type, pattern, captureIndex) {
|
||||
var captures = scan(pattern);
|
||||
if (captures) {
|
||||
return {
|
||||
type: type,
|
||||
value: captures[captureIndex]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function scan(regexp) {
|
||||
var captures,
|
||||
blankCaptures;
|
||||
|
||||
blankCaptures = /^[\n\r\t\s]+/.exec(input);
|
||||
if (blankCaptures) {
|
||||
consume(blankCaptures[0].length);
|
||||
}
|
||||
|
||||
captures = regexp.exec(input);
|
||||
if (captures) {
|
||||
consume(captures[0].length);
|
||||
}
|
||||
|
||||
return captures;
|
||||
}
|
||||
|
||||
function consume(size) {
|
||||
input = input.substr(size);
|
||||
}
|
||||
|
||||
return function(code) {
|
||||
input = code.toString();
|
||||
return getAST();
|
||||
};
|
||||
})();
|
||||
|
||||
exports.parse = GradientParser.parse;
|
||||
exports.stringify = GradientParser.stringify;
|
515
build/web.js
Normal file
515
build/web.js
Normal file
|
@ -0,0 +1,515 @@
|
|||
var GradientParser = (window.GradientParser || {});
|
||||
|
||||
// Copyright (c) 2014 Rafael Caricio. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var GradientParser = (GradientParser || {});
|
||||
|
||||
GradientParser.parse = (function() {
|
||||
|
||||
var tokens = {
|
||||
linearGradient: /^(\-(webkit|o|ms|moz)\-)?(linear\-gradient)/i,
|
||||
repeatingLinearGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-linear\-gradient)/i,
|
||||
radialGradient: /^(\-(webkit|o|ms|moz)\-)?(radial\-gradient)/i,
|
||||
repeatingRadialGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/i,
|
||||
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
|
||||
extentKeywords: /^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,
|
||||
positionKeywords: /^(left|center|right|top|bottom)/i,
|
||||
pixelValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))px/,
|
||||
percentageValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))\%/,
|
||||
emValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))em/,
|
||||
angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
|
||||
startCall: /^\(/,
|
||||
endCall: /^\)/,
|
||||
comma: /^,/,
|
||||
hexColor: /^\#([0-9a-fA-F]+)/,
|
||||
literalColor: /^([a-zA-Z]+)/,
|
||||
rgbColor: /^rgb/i,
|
||||
rgbaColor: /^rgba/i,
|
||||
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/
|
||||
};
|
||||
|
||||
var input = '';
|
||||
|
||||
function error(msg) {
|
||||
var err = new Error(input + ': ' + msg);
|
||||
err.source = input;
|
||||
throw err;
|
||||
}
|
||||
|
||||
function getAST() {
|
||||
var ast = matchListDefinitions();
|
||||
|
||||
if (input.length > 0) {
|
||||
error('Invalid input not EOF');
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
function matchListDefinitions() {
|
||||
return matchListing(matchDefinition);
|
||||
}
|
||||
|
||||
function matchDefinition() {
|
||||
return matchGradient(
|
||||
'linear-gradient',
|
||||
tokens.linearGradient,
|
||||
matchLinearOrientation) ||
|
||||
|
||||
matchGradient(
|
||||
'repeating-linear-gradient',
|
||||
tokens.repeatingLinearGradient,
|
||||
matchLinearOrientation) ||
|
||||
|
||||
matchGradient(
|
||||
'radial-gradient',
|
||||
tokens.radialGradient,
|
||||
matchListRadialOrientations) ||
|
||||
|
||||
matchGradient(
|
||||
'repeating-radial-gradient',
|
||||
tokens.repeatingRadialGradient,
|
||||
matchListRadialOrientations);
|
||||
}
|
||||
|
||||
function matchGradient(gradientType, pattern, orientationMatcher) {
|
||||
return matchCall(pattern, function(captures) {
|
||||
|
||||
var orientation = orientationMatcher();
|
||||
if (orientation) {
|
||||
if (!scan(tokens.comma)) {
|
||||
error('Missing comma before color stops');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: gradientType,
|
||||
orientation: orientation,
|
||||
colorStops: matchListing(matchColorStop)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchCall(pattern, callback) {
|
||||
var captures = scan(pattern);
|
||||
|
||||
if (captures) {
|
||||
if (!scan(tokens.startCall)) {
|
||||
error('Missing (');
|
||||
}
|
||||
|
||||
var result = callback(captures);
|
||||
|
||||
if (!scan(tokens.endCall)) {
|
||||
error('Missing )');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function matchLinearOrientation() {
|
||||
return matchSideOrCorner() ||
|
||||
matchAngle();
|
||||
}
|
||||
|
||||
function matchSideOrCorner() {
|
||||
return match('directional', tokens.sideOrCorner, 1);
|
||||
}
|
||||
|
||||
function matchAngle() {
|
||||
return match('angular', tokens.angleValue, 1);
|
||||
}
|
||||
|
||||
function matchListRadialOrientations() {
|
||||
var radialOrientations,
|
||||
radialOrientation = matchRadialOrientation(),
|
||||
lookaheadCache;
|
||||
|
||||
if (radialOrientation) {
|
||||
radialOrientations = [];
|
||||
radialOrientations.push(radialOrientation);
|
||||
|
||||
lookaheadCache = input;
|
||||
if (scan(tokens.comma)) {
|
||||
radialOrientation = matchRadialOrientation();
|
||||
if (radialOrientation) {
|
||||
radialOrientations.push(radialOrientation);
|
||||
} else {
|
||||
input = lookaheadCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return radialOrientations;
|
||||
}
|
||||
|
||||
function matchRadialOrientation() {
|
||||
var radialType = matchCircle() ||
|
||||
matchEllipse();
|
||||
|
||||
if (radialType) {
|
||||
radialType.at = matchAtPosition();
|
||||
} else {
|
||||
var extent = matchExtentKeyword();
|
||||
if (extent) {
|
||||
radialType = extent;
|
||||
var positionAt = matchAtPosition();
|
||||
if (positionAt) {
|
||||
radialType.at = positionAt;
|
||||
}
|
||||
} else {
|
||||
var defaultPosition = matchPositioning();
|
||||
if (defaultPosition) {
|
||||
radialType = {
|
||||
type: 'default-radial',
|
||||
at: defaultPosition
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return radialType;
|
||||
}
|
||||
|
||||
function matchCircle() {
|
||||
var circle = match('shape', /^(circle)/i, 0);
|
||||
|
||||
if (circle) {
|
||||
circle.style = matchLength() || matchExtentKeyword();
|
||||
}
|
||||
|
||||
return circle;
|
||||
}
|
||||
|
||||
function matchEllipse() {
|
||||
var ellipse = match('shape', /^(ellipse)/i, 0);
|
||||
|
||||
if (ellipse) {
|
||||
ellipse.style = matchDistance() || matchExtentKeyword();
|
||||
}
|
||||
|
||||
return ellipse;
|
||||
}
|
||||
|
||||
function matchExtentKeyword() {
|
||||
return match('extent-keyword', tokens.extentKeywords, 1);
|
||||
}
|
||||
|
||||
function matchAtPosition() {
|
||||
if (match('position', /^at/, 0)) {
|
||||
var positioning = matchPositioning();
|
||||
|
||||
if (!positioning) {
|
||||
error('Missing positioning value');
|
||||
}
|
||||
|
||||
return positioning;
|
||||
}
|
||||
}
|
||||
|
||||
function matchPositioning() {
|
||||
var location = matchCoordinates();
|
||||
|
||||
if (location.x || location.y) {
|
||||
return {
|
||||
type: 'position',
|
||||
value: location
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function matchCoordinates() {
|
||||
return {
|
||||
x: matchDistance(),
|
||||
y: matchDistance()
|
||||
};
|
||||
}
|
||||
|
||||
function matchListing(matcher) {
|
||||
var captures = matcher(),
|
||||
result = [];
|
||||
|
||||
if (captures) {
|
||||
result.push(captures);
|
||||
while (scan(tokens.comma)) {
|
||||
captures = matcher();
|
||||
if (captures) {
|
||||
result.push(captures);
|
||||
} else {
|
||||
error('One extra comma');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function matchColorStop() {
|
||||
var color = matchColor();
|
||||
|
||||
if (!color) {
|
||||
error('Expected color definition');
|
||||
}
|
||||
|
||||
color.length = matchDistance();
|
||||
return color;
|
||||
}
|
||||
|
||||
function matchColor() {
|
||||
return matchHexColor() ||
|
||||
matchRGBAColor() ||
|
||||
matchRGBColor() ||
|
||||
matchLiteralColor();
|
||||
}
|
||||
|
||||
function matchLiteralColor() {
|
||||
return match('literal', tokens.literalColor, 0);
|
||||
}
|
||||
|
||||
function matchHexColor() {
|
||||
return match('hex', tokens.hexColor, 1);
|
||||
}
|
||||
|
||||
function matchRGBColor() {
|
||||
return matchCall(tokens.rgbColor, function() {
|
||||
return {
|
||||
type: 'rgb',
|
||||
value: matchListing(matchNumber)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchRGBAColor() {
|
||||
return matchCall(tokens.rgbaColor, function() {
|
||||
return {
|
||||
type: 'rgba',
|
||||
value: matchListing(matchNumber)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchNumber() {
|
||||
return scan(tokens.number)[1];
|
||||
}
|
||||
|
||||
function matchDistance() {
|
||||
return match('%', tokens.percentageValue, 1) ||
|
||||
matchPositionKeyword() ||
|
||||
matchLength();
|
||||
}
|
||||
|
||||
function matchPositionKeyword() {
|
||||
return match('position-keyword', tokens.positionKeywords, 1);
|
||||
}
|
||||
|
||||
function matchLength() {
|
||||
return match('px', tokens.pixelValue, 1) ||
|
||||
match('em', tokens.emValue, 1);
|
||||
}
|
||||
|
||||
function match(type, pattern, captureIndex) {
|
||||
var captures = scan(pattern);
|
||||
if (captures) {
|
||||
return {
|
||||
type: type,
|
||||
value: captures[captureIndex]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function scan(regexp) {
|
||||
var captures,
|
||||
blankCaptures;
|
||||
|
||||
blankCaptures = /^[\n\r\t\s]+/.exec(input);
|
||||
if (blankCaptures) {
|
||||
consume(blankCaptures[0].length);
|
||||
}
|
||||
|
||||
captures = regexp.exec(input);
|
||||
if (captures) {
|
||||
consume(captures[0].length);
|
||||
}
|
||||
|
||||
return captures;
|
||||
}
|
||||
|
||||
function consume(size) {
|
||||
input = input.substr(size);
|
||||
}
|
||||
|
||||
return function(code) {
|
||||
input = code.toString();
|
||||
return getAST();
|
||||
};
|
||||
})();
|
||||
|
||||
// Copyright (c) 2014 Rafael Caricio. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var GradientParser = (GradientParser || {});
|
||||
|
||||
GradientParser.stringify = (function() {
|
||||
|
||||
var visitor = {
|
||||
|
||||
'visit_linear-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_repeating-linear-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_radial-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_repeating-radial-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_gradient': function(node) {
|
||||
var orientation = visitor.visit(node.orientation);
|
||||
if (orientation) {
|
||||
orientation += ', ';
|
||||
}
|
||||
|
||||
return node.type + '(' + orientation + visitor.visit(node.colorStops) + ')';
|
||||
},
|
||||
|
||||
'visit_shape': function(node) {
|
||||
var result = node.value,
|
||||
at = visitor.visit(node.at),
|
||||
style = visitor.visit(node.style);
|
||||
|
||||
if (style) {
|
||||
result += ' ' + style;
|
||||
}
|
||||
|
||||
if (at) {
|
||||
result += ' at ' + at;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_default-radial': function(node) {
|
||||
var result = '',
|
||||
at = visitor.visit(node.at);
|
||||
|
||||
if (at) {
|
||||
result += at;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_extent-keyword': function(node) {
|
||||
var result = node.value,
|
||||
at = visitor.visit(node.at);
|
||||
|
||||
if (at) {
|
||||
result += ' at ' + at;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_position-keyword': function(node) {
|
||||
return node.value;
|
||||
},
|
||||
|
||||
'visit_position': function(node) {
|
||||
return visitor.visit(node.value.x) + ' ' + visitor.visit(node.value.y);
|
||||
},
|
||||
|
||||
'visit_%': function(node) {
|
||||
return node.value + '%';
|
||||
},
|
||||
|
||||
'visit_em': function(node) {
|
||||
return node.value + 'em';
|
||||
},
|
||||
|
||||
'visit_px': function(node) {
|
||||
return node.value + 'px';
|
||||
},
|
||||
|
||||
'visit_literal': function(node) {
|
||||
return visitor.visit_color(node.value, node);
|
||||
},
|
||||
|
||||
'visit_hex': function(node) {
|
||||
return visitor.visit_color('#' + node.value, node);
|
||||
},
|
||||
|
||||
'visit_rgb': function(node) {
|
||||
return visitor.visit_color('rgb(' + node.value.join(', ') + ')', node);
|
||||
},
|
||||
|
||||
'visit_rgba': function(node) {
|
||||
return visitor.visit_color('rgba(' + node.value.join(', ') + ')', node);
|
||||
},
|
||||
|
||||
'visit_color': function(resultColor, node) {
|
||||
var result = resultColor,
|
||||
length = visitor.visit(node.length);
|
||||
|
||||
if (length) {
|
||||
result += ' ' + length;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_angular': function(node) {
|
||||
return node.value + 'deg';
|
||||
},
|
||||
|
||||
'visit_directional': function(node) {
|
||||
return 'to ' + node.value;
|
||||
},
|
||||
|
||||
'visit_array': function(elements) {
|
||||
var result = '',
|
||||
size = elements.length;
|
||||
|
||||
elements.forEach(function(element, i) {
|
||||
result += visitor.visit(element);
|
||||
if (i < size - 1) {
|
||||
result += ', ';
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit': function(element) {
|
||||
if (!element) {
|
||||
return '';
|
||||
}
|
||||
var result = '';
|
||||
|
||||
if (element instanceof Array) {
|
||||
return visitor.visit_array(element, result);
|
||||
} else if (element.type) {
|
||||
var nodeVisitor = visitor['visit_' + element.type];
|
||||
if (nodeVisitor) {
|
||||
return nodeVisitor(element);
|
||||
} else {
|
||||
throw Error('Missing visitor visit_' + element.type);
|
||||
}
|
||||
} else {
|
||||
throw Error('Invalid node.');
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return function(root) {
|
||||
return visitor.visit(root);
|
||||
};
|
||||
})();
|
10
gruntfile.js
10
gruntfile.js
|
@ -15,12 +15,22 @@ module.exports = function (grunt) {
|
|||
},
|
||||
src: ['spec/**/*.js']
|
||||
}
|
||||
},
|
||||
concat: {
|
||||
release: {
|
||||
files: {
|
||||
'build/node.js': ['lib/stringify.js', 'lib/parser.js', 'index.js'],
|
||||
'build/web.js': ['webify.js', 'lib/parser.js', 'lib/stringify.js']
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-mocha-test');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
|
||||
grunt.registerTask('default', [
|
||||
'concat',
|
||||
'mochaTest'
|
||||
]);
|
||||
};
|
||||
|
|
12
index.html
Normal file
12
index.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="build/web.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.body.innerHTML = '<pre>'+ JSON.stringify(GradientParser.parse('radial-gradient(ellipse cover, rgb(0, 57, 115), rgb(229, 229, 190))'), null, 2) +'</pre>';
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
3
index.js
3
index.js
|
@ -1 +1,2 @@
|
|||
exports.parse = require('./lib/parser');
|
||||
exports.parse = GradientParser.parse;
|
||||
exports.stringify = GradientParser.stringify;
|
||||
|
|
|
@ -2,39 +2,22 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
module.exports = (function() {
|
||||
var GradientParser = (GradientParser || {});
|
||||
|
||||
var types = {
|
||||
gradients: [
|
||||
'linear-gradient',
|
||||
'repeating-linear-gradient',
|
||||
'radial-gradient',
|
||||
'repeating-radial-gradient'
|
||||
],
|
||||
colors: [
|
||||
'hex',
|
||||
'rgb',
|
||||
'rgba',
|
||||
'hsl',
|
||||
'literal'
|
||||
],
|
||||
metrics: [
|
||||
'px'
|
||||
]
|
||||
};
|
||||
GradientParser.parse = (function() {
|
||||
|
||||
var tokens = {
|
||||
linearGradient: /^linear\-gradient/i,
|
||||
repeatingLinearGradient: /^repeating\-linear\-gradient/i,
|
||||
radialGradient: /^radial\-gradient/i,
|
||||
repeatingRadialGradient: /^repeating\-radial\-gradient/i,
|
||||
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
|
||||
linearGradient: /^(\-(webkit|o|ms|moz)\-)?(linear\-gradient)/i,
|
||||
repeatingLinearGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-linear\-gradient)/i,
|
||||
radialGradient: /^(\-(webkit|o|ms|moz)\-)?(radial\-gradient)/i,
|
||||
repeatingRadialGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/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)/,
|
||||
positionKeywords: /^(left|center|right|top|bottom)/i,
|
||||
pixelValue: /^([0-9]+)px/,
|
||||
percentageValue: /^([0-9]+)\%/,
|
||||
emValue: /^([0-9]+)em/,
|
||||
angleValue: /^([0-9]+)deg/,
|
||||
pixelValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))px/,
|
||||
percentageValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))\%/,
|
||||
emValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))em/,
|
||||
angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
|
||||
startCall: /^\(/,
|
||||
endCall: /^\)/,
|
||||
comma: /^,/,
|
||||
|
@ -115,7 +98,7 @@ module.exports = (function() {
|
|||
error('Missing (');
|
||||
}
|
||||
|
||||
result = callback(captures);
|
||||
var result = callback(captures);
|
||||
|
||||
if (!scan(tokens.endCall)) {
|
||||
error('Missing )');
|
||||
|
@ -168,12 +151,21 @@ module.exports = (function() {
|
|||
if (radialType) {
|
||||
radialType.at = matchAtPosition();
|
||||
} else {
|
||||
var defaultPosition = matchPositioning();
|
||||
if (defaultPosition) {
|
||||
radialType = {
|
||||
type: 'default-radial',
|
||||
at: defaultPosition
|
||||
};
|
||||
var extent = matchExtentKeyword();
|
||||
if (extent) {
|
||||
radialType = extent;
|
||||
var positionAt = matchAtPosition();
|
||||
if (positionAt) {
|
||||
radialType.at = positionAt;
|
||||
}
|
||||
} else {
|
||||
var defaultPosition = matchPositioning();
|
||||
if (defaultPosition) {
|
||||
radialType = {
|
||||
type: 'default-radial',
|
||||
at: defaultPosition
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
166
lib/stringify.js
Normal file
166
lib/stringify.js
Normal file
|
@ -0,0 +1,166 @@
|
|||
// Copyright (c) 2014 Rafael Caricio. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var GradientParser = (GradientParser || {});
|
||||
|
||||
GradientParser.stringify = (function() {
|
||||
|
||||
var visitor = {
|
||||
|
||||
'visit_linear-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_repeating-linear-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_radial-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_repeating-radial-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_gradient': function(node) {
|
||||
var orientation = visitor.visit(node.orientation);
|
||||
if (orientation) {
|
||||
orientation += ', ';
|
||||
}
|
||||
|
||||
return node.type + '(' + orientation + visitor.visit(node.colorStops) + ')';
|
||||
},
|
||||
|
||||
'visit_shape': function(node) {
|
||||
var result = node.value,
|
||||
at = visitor.visit(node.at),
|
||||
style = visitor.visit(node.style);
|
||||
|
||||
if (style) {
|
||||
result += ' ' + style;
|
||||
}
|
||||
|
||||
if (at) {
|
||||
result += ' at ' + at;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_default-radial': function(node) {
|
||||
var result = '',
|
||||
at = visitor.visit(node.at);
|
||||
|
||||
if (at) {
|
||||
result += at;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_extent-keyword': function(node) {
|
||||
var result = node.value,
|
||||
at = visitor.visit(node.at);
|
||||
|
||||
if (at) {
|
||||
result += ' at ' + at;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_position-keyword': function(node) {
|
||||
return node.value;
|
||||
},
|
||||
|
||||
'visit_position': function(node) {
|
||||
return visitor.visit(node.value.x) + ' ' + visitor.visit(node.value.y);
|
||||
},
|
||||
|
||||
'visit_%': function(node) {
|
||||
return node.value + '%';
|
||||
},
|
||||
|
||||
'visit_em': function(node) {
|
||||
return node.value + 'em';
|
||||
},
|
||||
|
||||
'visit_px': function(node) {
|
||||
return node.value + 'px';
|
||||
},
|
||||
|
||||
'visit_literal': function(node) {
|
||||
return visitor.visit_color(node.value, node);
|
||||
},
|
||||
|
||||
'visit_hex': function(node) {
|
||||
return visitor.visit_color('#' + node.value, node);
|
||||
},
|
||||
|
||||
'visit_rgb': function(node) {
|
||||
return visitor.visit_color('rgb(' + node.value.join(', ') + ')', node);
|
||||
},
|
||||
|
||||
'visit_rgba': function(node) {
|
||||
return visitor.visit_color('rgba(' + node.value.join(', ') + ')', node);
|
||||
},
|
||||
|
||||
'visit_color': function(resultColor, node) {
|
||||
var result = resultColor,
|
||||
length = visitor.visit(node.length);
|
||||
|
||||
if (length) {
|
||||
result += ' ' + length;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_angular': function(node) {
|
||||
return node.value + 'deg';
|
||||
},
|
||||
|
||||
'visit_directional': function(node) {
|
||||
return 'to ' + node.value;
|
||||
},
|
||||
|
||||
'visit_array': function(elements) {
|
||||
var result = '',
|
||||
size = elements.length;
|
||||
|
||||
elements.forEach(function(element, i) {
|
||||
result += visitor.visit(element);
|
||||
if (i < size - 1) {
|
||||
result += ', ';
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit': function(element) {
|
||||
if (!element) {
|
||||
return '';
|
||||
}
|
||||
var result = '';
|
||||
|
||||
if (element instanceof Array) {
|
||||
return visitor.visit_array(element, result);
|
||||
} else if (element.type) {
|
||||
var nodeVisitor = visitor['visit_' + element.type];
|
||||
if (nodeVisitor) {
|
||||
return nodeVisitor(element);
|
||||
} else {
|
||||
throw Error('Missing visitor visit_' + element.type);
|
||||
}
|
||||
} else {
|
||||
throw Error('Invalid node.');
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return function(root) {
|
||||
return visitor.visit(root);
|
||||
};
|
||||
})();
|
10999
package-lock.json
generated
Normal file
10999
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gradient-parser",
|
||||
"version": "0.1.0",
|
||||
"version": "1.0.2",
|
||||
"description": "Parse CSS3 gradient definitions and return an AST.",
|
||||
"author": {
|
||||
"name": "Rafael Carcicio",
|
||||
|
@ -23,7 +23,7 @@
|
|||
"type": "git",
|
||||
"url": "git://github.com/rafaelcaricio/gradient-parser.git"
|
||||
},
|
||||
"main": "index.js",
|
||||
"main": "build/node.js",
|
||||
"scripts": {
|
||||
"test": "grunt"
|
||||
},
|
||||
|
@ -32,10 +32,12 @@
|
|||
"css3",
|
||||
"parser"
|
||||
],
|
||||
"dependencies": {},
|
||||
"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": "*"
|
||||
|
|
|
@ -1,37 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var expect = require('expect.js');
|
||||
var gradients = require('index');
|
||||
var gradients = require('../build/node');
|
||||
|
||||
// [
|
||||
// {
|
||||
// type: 'linear-gradient',
|
||||
// orientation: {
|
||||
// type: 'directional',
|
||||
// value: 'right'
|
||||
// },
|
||||
// colorStops: [
|
||||
// {
|
||||
// type: 'literal',
|
||||
// value: 'transparent',
|
||||
// length: {
|
||||
// value: '10',
|
||||
// type: 'px'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// type: 'hex',
|
||||
// value: 'c2c2c2',
|
||||
// length: {
|
||||
// value: '10',
|
||||
// type: 'px'
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
|
||||
describe('gradient-parser.js', function () {
|
||||
describe('lib/parser.js', function () {
|
||||
var ast,
|
||||
subject;
|
||||
|
||||
|
@ -42,13 +15,13 @@ describe('gradient-parser.js', function () {
|
|||
describe('error cases', function() {
|
||||
it('one more comma in definitions', function() {
|
||||
expect(function() {
|
||||
gradients.parse('linear-gradient(red, blue),');
|
||||
gradients.parse('-webkit-linear-gradient(red, blue),');
|
||||
}).to.throwException(/One extra comma/);
|
||||
});
|
||||
|
||||
it('one more comma in colors', function() {
|
||||
expect(function() {
|
||||
gradients.parse('linear-gradient(red, blue,)');
|
||||
gradients.parse('-o-linear-gradient(red, blue,)');
|
||||
}).to.throwException(/Expected color definition/);
|
||||
});
|
||||
|
||||
|
@ -140,7 +113,7 @@ describe('gradient-parser.js', function () {
|
|||
].forEach(function(metric) {
|
||||
describe('parse color stop for metric '+ metric, function() {
|
||||
beforeEach(function() {
|
||||
ast = gradients.parse('linear-gradient(blue 10' + metric + ', transparent)');
|
||||
ast = gradients.parse('linear-gradient(blue 10.3' + metric + ', transparent)');
|
||||
subject = ast[0];
|
||||
});
|
||||
|
||||
|
@ -151,7 +124,7 @@ describe('gradient-parser.js', function () {
|
|||
|
||||
it('should have the length', function() {
|
||||
expect(subject.length.type).to.equal(metric);
|
||||
expect(subject.length.value).to.equal('10');
|
||||
expect(subject.length.value).to.equal('10.3');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -160,8 +133,12 @@ describe('gradient-parser.js', function () {
|
|||
|
||||
describe('parse all linear directional', function() {
|
||||
[
|
||||
{type: 'angular', unparsedValue: '145deg', value: '145'},
|
||||
{type: 'directional', unparsedValue: 'to left top', value: 'left top'}
|
||||
{type: 'angular', unparsedValue: '-145deg', value: '-145'},
|
||||
{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) {
|
||||
describe('parse orientation ' + orientation.type, function() {
|
||||
beforeEach(function() {
|
||||
|
@ -224,7 +201,10 @@ describe('gradient-parser.js', function () {
|
|||
'ellipse cover',
|
||||
'circle cover',
|
||||
'center bottom, ellipse cover',
|
||||
'circle at 119px 58px'
|
||||
'circle at 87.23px -58.3px',
|
||||
'farthest-side, red, blue',
|
||||
'farthest-corner, red, blue',
|
||||
'farthest-corner at 87.23px -58.3px, red, blue'
|
||||
].forEach(function(declaration) {
|
||||
|
||||
it('should parse ' + declaration + ' declaration', function() {
|
||||
|
|
100
spec/stringify.spec.js
Normal file
100
spec/stringify.spec.js
Normal file
|
@ -0,0 +1,100 @@
|
|||
'use strict';
|
||||
|
||||
var expect = require('expect.js');
|
||||
var gradients = require('../build/node');
|
||||
|
||||
function pprint(ast) {
|
||||
console.log(JSON.stringify(ast, true, 2));
|
||||
}
|
||||
|
||||
describe('lib/stringify.js', function () {
|
||||
var subject;
|
||||
|
||||
it('should exist', function () {
|
||||
expect(typeof gradients.stringify).to.equal('function');
|
||||
});
|
||||
|
||||
describe('serialization', function() {
|
||||
|
||||
it('if tree is null', function() {
|
||||
expect(gradients.stringify(null)).to.equal('');
|
||||
});
|
||||
|
||||
it('should serialize a simple gradient', function() {
|
||||
var gradientDef = 'linear-gradient(black, white)';
|
||||
expect(gradients.stringify(gradients.parse(gradientDef))).to.equal(gradientDef);
|
||||
});
|
||||
|
||||
it('should serialize gradient with hex', function() {
|
||||
var gradientDef = 'linear-gradient(#fff, white)';
|
||||
expect(gradients.stringify(gradients.parse(gradientDef))).to.equal(gradientDef);
|
||||
});
|
||||
|
||||
it('should serialize gradient with rgb', function() {
|
||||
var gradientDef = 'linear-gradient(rgb(1, 2, 3), white)';
|
||||
expect(gradients.stringify(gradients.parse(gradientDef))).to.equal(gradientDef);
|
||||
});
|
||||
|
||||
it('should serialize gradient with rgba', function() {
|
||||
var gradientDef = 'linear-gradient(rgba(1, 2, 3, .0), white)';
|
||||
expect(gradients.stringify(gradients.parse(gradientDef))).to.equal(gradientDef);
|
||||
});
|
||||
|
||||
it('should serialize gradient with deg', function() {
|
||||
var gradientDef = 'linear-gradient(45deg, #fff, transparent)';
|
||||
expect(gradients.stringify(gradients.parse(gradientDef))).to.equal(gradientDef);
|
||||
});
|
||||
|
||||
it('should serialize gradient with directional', function() {
|
||||
var gradientDef = 'linear-gradient(to left, #fff, transparent)';
|
||||
expect(gradients.stringify(gradients.parse(gradientDef))).to.equal(gradientDef);
|
||||
});
|
||||
|
||||
describe('all metric values', function() {
|
||||
[
|
||||
'px',
|
||||
'em',
|
||||
'%'
|
||||
].forEach(function(metric) {
|
||||
var expectedResult;
|
||||
|
||||
describe('stringify color stop for metric '+ metric, function() {
|
||||
beforeEach(function() {
|
||||
expectedResult = 'linear-gradient(blue 10.3' + metric + ', transparent)';
|
||||
var ast = gradients.parse(expectedResult);
|
||||
subject = gradients.stringify(ast);
|
||||
});
|
||||
|
||||
it('should result as expected', function() {
|
||||
expect(subject).to.equal(expectedResult);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('different radial declarations', function() {
|
||||
[
|
||||
'ellipse farthest-corner',
|
||||
'ellipse cover',
|
||||
'circle cover',
|
||||
'center bottom, ellipse cover',
|
||||
'circle at 87.23px -58.3px',
|
||||
'farthest-corner, red, blue',
|
||||
'farthest-corner at 87.23px -58.3px, red, blue'
|
||||
].forEach(function(declaration) {
|
||||
|
||||
it('should parse ' + declaration + ' declaration', function() {
|
||||
var expectedResult = 'radial-gradient(' + declaration + ', red, blue)';
|
||||
var ast = gradients.parse(expectedResult);
|
||||
subject = gradients.stringify(ast);
|
||||
|
||||
expect(subject).to.equal(expectedResult);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in a new issue