Why is this Less expression a syntax error dependi

2019-03-01 08:26发布

I have the following snippet of Less:

@Foo: 50px;

.someClass {
    width: calc(~'(100% - @{Foo}' - 5px);
}

This works fine. However, if I change this to:

@Foo: 50px;

.someClass {
    width: calc(~'(100% - @{Foo}' + 5px);
}

We now have a ParseError. We're on a bit older version of Less, but I've tried it on the official Less preview site and it still breaks.

Is this a bug or am I doing something silly?

标签: less
1条回答
女痞
2楼-- · 2019-03-01 09:09

This is a very interesting case. The below code compiles fine and produces the expected output when --strict-math setting is turned on (--strict-math=on).

@Foo: 50px;
.someClass {
  width: calc(e('(100% - @{Foo}') - 5px);
}
.someClass {
  width: calc(e('(100% - @{Foo}') + 5px);
}

When strict math is turned off (which is, the default), both lines result in compiler error. Error message is given below and it is indicative of the fact that Less compiler is trying to perform math operations on values inside the calc function. This aggressive compilation is a known behavior of Less compiler.

OperationError: Operation on an invalid type

As confirmed by seven-phases-max in his comment, the behavior with the e() function (both when strict math is turned on and when it is turned off) is correct and error message also is as expected.


Ideally the same behavior as above should be seen for ~"" syntax also because it is a replacement of the e(). But unfortunately it doesn't seem to be. The code fails to compile irrespective of whether the strict math setting is enabled or not and the error message shown is the following:

ParseError: Could not parse call arguments or missing ')'

The error message indicates it is Parse Error and not an Operation Error. As seven-phases-max has indicated, it seems like the parser is not expecting an arithmetic operator to follow a value that is not a number and hence is throwing a parser error. The error message could've been more friendly :)

This problem happens only when the operator is + or * and not when it is - or /. When - or / is used, they can't always be considered as math operator (because - is used in prefixes and / is used in font property for line-height etc) and so compiler processes them as an identifier but + or * is invariably a math operator and so causes the issue. When - or / is used, it just results in string concatenation.


The below is the recommended way to fix this issue as it doesn't make the compiler to think that some kind of math operation has to be performed (and leaves it to the User Agent to handle as part of CSS):

@Foo: 50px;
.someClass {
  width: calc(~'(100% - @{Foo} - 5px');
}
.someClass {
  width: calc(~'(100% - @{Foo} + 5px');
}

Note: There is a missing close brace ()) within the calc functions but that is irrelevant to this case.

查看更多
登录 后发表回答