Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

added support for calc wherever <length> is expected #35

Merged
merged 3 commits into from

2 participants

@fracmak

According to https://developer.mozilla.org/en-US/docs/CSS/calc

calc is supported wherever a length property value is supported.

This adds support for a calc() function, and adds support for the *, +, and - operators to successfully parse out the calc functions.

Unit tests updated

@nzakas
Owner

wow, thanks I'll take a look next week.

@nzakas
Owner

This looks like a good start. What it's missing is a way to access that information correctly from the parser. Ideally, there would be a way to get access the various parts of the calc() function from inside the "property" event, as part of the value. Do you have any ideas for how to do that?

@fracmak

I'm very new to the parser lib, I was trying to solve a problem with css-lint that depended on parser-lib to verify whether css is valid and this lack of support was throwing errors in my build process. If you point me in the right direction I can look into adding support deeper into the library.

@nzakas
Owner

Understood. I'd just like to have a complete solution rather than a partial one. Right now, what you've implemented will make sure that the parser doesn't throw an error, but it doesn't make sure that somebody using the parser can get access to the data. A good place to start is with the description of syntax units here:

https://github.com/nzakas/parser-lib/blob/master/docs/css.md

Each value is split into instances of PropertyValuePart (https://github.com/nzakas/parser-lib/blob/master/src/css/PropertyValuePart.js). I'm not sure what would happen right now if you listen for a "property" event and look at the value when using calc(). That would be a good place to start. Ideally, the parser should return something that gives you access to all the parts of the calculation.

It's a bit of work, I'm sure - part of why I haven't dug into it yet. :)

@nzakas
Owner

After looking at this again, I'd like to merge it in however there is a test that's failing. (the Travis build isn't working correctly.) Run ant test from the command line to see it. If you can fix that, I'll be happy to merge in.

fracmak added some commits
@fracmak fracmak added support for calc wherever <length> is expected 1845473
@fracmak fracmak added support for + operator for calc functions e0be226
@fracmak fracmak _operator is used for seperating multiple values for a property (ie. …
…box-shadow: 10px 10px 0, 2px 2px 0) as well as for mathematical operators inside functions. Since functions are the only place mathematical operators are allowed, we now pass in a boolean to distinguish which token is acceptable to not accidentally treat -10px -10px as an equation
ebf3f4a
@fracmak

I've dug through the code and found out where my logic went wrong. the _operator() function is used for seperation of compound css statements as well as parsing parameters in a function. When I added the mathematical operators to the list, it broke scenarios like box-shadow: 10px 10px #888, -10px -10px #f4f4f4; because it thought it was a mathematical operator. I've added a boolean to the _operator function to indicate whether we're parsing inside a function or outside since the math operators are only allowed inside. This has fixed the test.

@nzakas nzakas merged commit 8ca2d38 into CSSLint:master

1 check passed

Details default The Travis build passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 14, 2012
  1. @fracmak

    added support for calc wherever <length> is expected

    fracmak authored fracmak committed
  2. @fracmak

    added support for + operator for calc functions

    fracmak authored fracmak committed
  3. @fracmak

    _operator is used for seperating multiple values for a property (ie. …

    fracmak authored
    …box-shadow: 10px 10px 0, 2px 2px 0) as well as for mathematical operators inside functions. Since functions are the only place mathematical operators are allowed, we now pass in a boolean to distinguish which token is acceptable to not accidentally treat -10px -10px as an equation
This page is out of date. Refresh to see the latest.
View
17 src/css/Parser.js
@@ -708,18 +708,21 @@ Parser.prototype = function(){
});
},
- _operator: function(){
+ _operator: function(inFunction){
/*
- * operator
+ * operator (outside function)
* : '/' S* | ',' S* | /( empty )/
+ * operator (inside function)
+ * : '/' S* | '+' S* | '*' S* | '-' S* /( empty )/
* ;
*/
var tokenStream = this._tokenStream,
token = null;
- if (tokenStream.match([Tokens.SLASH, Tokens.COMMA])){
+ if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) ||
+ (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))){
token = tokenStream.token();
this._readWhitespace();
}
@@ -1506,7 +1509,7 @@ Parser.prototype = function(){
return result;
},
- _expr: function(){
+ _expr: function(inFunction){
/*
* expr
* : term [ operator term ]*
@@ -1525,8 +1528,8 @@ Parser.prototype = function(){
values.push(value);
do {
- operator = this._operator();
-
+ operator = this._operator(inFunction);
+
//if there's an operator, keep building up the value parts
if (operator){
values.push(operator);
@@ -1662,7 +1665,7 @@ Parser.prototype = function(){
if (tokenStream.match(Tokens.FUNCTION)){
functionText = tokenStream.token().value;
this._readWhitespace();
- expr = this._expr();
+ expr = this._expr(true);
functionText += expr;
//START: Horrible hack in case it's an IE filter
View
6 src/css/ValidationTypes.js
@@ -121,7 +121,11 @@ var ValidationTypes = {
},
"<length>": function(part){
- return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0";
+ if (part.type == "function" && /^(?:\-(?:ms|moz|o|webkit)\-)?calc/i.test(part)){
+ return true;
+ }else{
+ return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0";
+ }
},
"<color>": function(part){
View
1  tests/css/CSSTokensTests.htm
@@ -420,6 +420,7 @@
//regular CSS functions
"rgb(255,0,1)" : [CSSTokens.FUNCTION, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.NUMBER, CSSTokens.RPAREN],
"counter(par-num,upper-roman)" : [CSSTokens.FUNCTION, CSSTokens.IDENT, CSSTokens.COMMA, CSSTokens.IDENT, CSSTokens.RPAREN],
+ "calc(100% - 5px)" : [CSSTokens.FUNCTION, CSSTokens.PERCENTAGE, CSSTokens.S, CSSTokens.MINUS, CSSTokens.S, CSSTokens.LENGTH, CSSTokens.RPAREN],
//old-style IE filters - interpreted as bunch of tokens
"alpha(opacity=50)" : [CSSTokens.FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN],
View
1  tests/css/TokenStream.js
@@ -405,6 +405,7 @@
//regular CSS functions
"rgb(255,0,1)" : [CSSTokens.FUNCTION, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.NUMBER, CSSTokens.RPAREN],
"counter(par-num,upper-roman)" : [CSSTokens.FUNCTION, CSSTokens.IDENT, CSSTokens.COMMA, CSSTokens.IDENT, CSSTokens.RPAREN],
+ "calc(100% - 5px)" : [CSSTokens.FUNCTION, CSSTokens.PERCENTAGE, CSSTokens.S, CSSTokens.MINUS, CSSTokens.S, CSSTokens.LENGTH, CSSTokens.RPAREN],
//old-style IE filters - interpreted as bunch of tokens
"alpha(opacity=50)" : [CSSTokens.FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN],
View
4 tests/css/Validation.js
@@ -492,6 +492,10 @@
valid: [
"1px",
"1%",
+ "calc(100% - 5px)",
+ "calc(100% + 1em)",
+ "calc(100%/6)",
+ "calc(10%*6)",
"inherit"
],
Something went wrong with that request. Please try again.