gradient-parser/gradient-parser.js

156 lines
3 KiB
JavaScript
Raw Normal View History

// 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.
2014-09-05 16:56:36 +00:00
module.exports = (function() {
var types = {
gradients: [
'linear-gradient',
'radial-gradient',
'repeating-radial-gradient'
],
colors: [
'hex',
'rgb',
'rgba',
'hsl',
'literal'
]
};
2014-09-05 00:02:54 +00:00
var tokens = {
linearGradient: /^linear\-gradient/i,
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
startCall: /^\(/,
endCall: /^\)/,
comma: /^,/
};
2014-09-05 16:56:36 +00:00
var input = '',
cursor = 0;
function error(msg) {
2014-09-05 08:28:40 +00:00
var err = new Error(input + ':' + cursor + ': ' + msg);
err.position = cursor;
err.message = msg;
err.source = input;
throw err;
}
2014-09-05 16:56:36 +00:00
function getAST() {
var ast = listDefinitions();
2014-09-05 08:28:40 +00:00
2014-09-05 16:56:36 +00:00
if (input.length > 0) {
2014-09-05 08:28:40 +00:00
error(input, cursor, 'Invalid input not EOF');
}
return ast;
2014-09-05 00:02:54 +00:00
};
2014-09-05 16:56:36 +00:00
function listDefinitions() {
2014-09-05 00:02:54 +00:00
var definitions = [],
2014-09-05 16:56:36 +00:00
currentDefinition = definition();
if (currentDefinition) {
definitions.push(currentDefinition);
while (scan(tokens.comma)) {
currentDefinition = definition();
if (currentDefinition) {
definitions.push(currentDefinition);
2014-09-05 00:02:54 +00:00
} else {
// throw error
}
2014-09-05 00:02:54 +00:00
}
}
return definitions;
2014-09-05 16:56:36 +00:00
}
2014-09-05 00:02:54 +00:00
2014-09-05 16:56:36 +00:00
function definition() {
return linearGradient();
}
2014-09-05 00:02:54 +00:00
2014-09-05 16:56:36 +00:00
function linearGradient() {
var captures = scan(tokens.linearGradient),
2014-09-05 00:02:54 +00:00
orientation,
colorStops;
if (captures) {
2014-09-05 16:56:36 +00:00
scan(tokens.startCall);
orientation = matchOrientation();
scan(tokens.comma);
colorStops = matchColorStops();
scan(tokens.endCall);
2014-09-05 00:02:54 +00:00
return {
type: 'linear-gradient',
orientation: orientation,
colorStops: colorStops
};
}
2014-09-05 16:56:36 +00:00
}
2014-09-05 00:02:54 +00:00
2014-09-05 16:56:36 +00:00
function matchOrientation() {
return sideOrCorner();
}
2014-09-05 00:02:54 +00:00
2014-09-05 16:56:36 +00:00
function sideOrCorner() {
var captures = scan(tokens.sideOrCorner);
2014-09-05 00:02:54 +00:00
if (captures) {
return {
type: 'directional',
value: captures[1].toLowerCase()
};
}
2014-09-05 16:56:36 +00:00
}
2014-09-05 00:02:54 +00:00
2014-09-05 16:56:36 +00:00
function matchColorStops() {
2014-09-05 00:02:54 +00:00
var literalColors = /^([a-zA-Z]+)/,
2014-09-05 16:56:36 +00:00
captures = scan(literalColors),
2014-09-05 00:02:54 +00:00
colors = [];
if (captures) {
colors.push(captures[0].toLowerCase());
2014-09-05 16:56:36 +00:00
while (scan(tokens.comma)) {
captures = scan(literalColors);
2014-09-05 00:02:54 +00:00
if (captures) {
colors.push(captures[0].toLowerCase());
} else {
// trow error
}
}
2014-09-05 00:02:54 +00:00
}
return colors;
2014-09-05 16:56:36 +00:00
}
2014-09-05 00:02:54 +00:00
2014-09-05 16:56:36 +00:00
function scan(regexp) {
2014-09-05 00:02:54 +00:00
var captures,
blankCaptures;
2014-09-05 16:56:36 +00:00
blankCaptures = /^[\n\r\t\s]+/.exec(input);
2014-09-05 00:02:54 +00:00
if (blankCaptures) {
2014-09-05 16:56:36 +00:00
consume(blankCaptures[0].length);
2014-09-05 00:02:54 +00:00
}
2014-09-05 16:56:36 +00:00
captures = regexp.exec(input);
2014-09-05 00:02:54 +00:00
if (captures) {
2014-09-05 16:56:36 +00:00
consume(captures[0].length);
2014-09-05 00:02:54 +00:00
}
return captures;
2014-09-05 16:56:36 +00:00
}
2014-09-05 00:02:54 +00:00
2014-09-05 16:56:36 +00:00
function consume(size) {
cursor += size;
input = input.substr(size);
}
2014-09-05 00:02:54 +00:00
2014-09-05 16:56:36 +00:00
return function(code) {
input = code.toString();
return getAST();
};
2014-09-05 00:02:54 +00:00
})();