Skip to content

Commit aa39efd

Browse files
committed
Bug fix in calc parsing when the first operand is a negative value
1 parent 8be357d commit aa39efd

File tree

3 files changed

+24
-17
lines changed

3 files changed

+24
-17
lines changed

lib/Sabberworm/CSS/Parser.php

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -555,34 +555,39 @@ private function parseURLValue() {
555555
}
556556

557557
private function parseCalcValue() {
558-
$aOperators = array('+', '-', '*', '/', '(', ')');
558+
$aOperators = array('+', '-', '*', '/');
559559
$sFunction = trim($this->consumeUntil('(', false, true));
560560
$oCalcList = new CalcRuleValueList($this->iLineNo);
561561
$oList = new RuleValueList(',', $this->iLineNo);
562562
$iNestingLevel = 0;
563563
$iLastComponentType = NULL;
564564
while(!$this->comes(')') || $iNestingLevel > 0) {
565565
$this->consumeWhiteSpace();
566-
if (in_array($this->peek(), $aOperators)) {
567-
if (($this->comes('-') || $this->comes('+'))) {
568-
if ($this->peek(1, -1) != ' ' || !($this->comes('- ') || $this->comes('+ '))) {
569-
throw new UnexpectedTokenException(" {$this->peek()} ", $this->peek(1, -1) . $this->peek(2), 'literal', $this->iLineNo);
570-
}
571-
} else if ($this->comes('(')) {
572-
$iNestingLevel++;
573-
} else if ($this->comes(')')) {
574-
$iNestingLevel--;
575-
}
566+
if ($this->comes('(')) {
567+
$iNestingLevel++;
576568
$oCalcList->addListComponent($this->consume(1));
577-
$iLastComponentType = CalcFunction::T_OPERATOR;
578-
} else {
569+
continue;
570+
} else if ($this->comes(')')) {
571+
$iNestingLevel--;
572+
$oCalcList->addListComponent($this->consume(1));
573+
continue;
574+
}
575+
if ($iLastComponentType != CalcFunction::T_OPERAND) {
579576
$oVal = $this->parsePrimitiveValue();
580-
if ($iLastComponentType == CalcFunction::T_OPERAND) {
581-
throw new UnexpectedTokenException(sprintf('Next token was expected to be an operand of type %s. Instead "%s" was found.', implode(', ', $aOperators), $oVal), '', 'custom', $this->iLineNo);
582-
}
583-
584577
$oCalcList->addListComponent($oVal);
585578
$iLastComponentType = CalcFunction::T_OPERAND;
579+
} else {
580+
if (in_array($this->peek(), $aOperators)) {
581+
if (($this->comes('-') || $this->comes('+'))) {
582+
if ($this->peek(1, -1) != ' ' || !($this->comes('- ') || $this->comes('+ '))) {
583+
throw new UnexpectedTokenException(" {$this->peek()} ", $this->peek(1, -1) . $this->peek(2), 'literal', $this->iLineNo);
584+
}
585+
}
586+
$oCalcList->addListComponent($this->consume(1));
587+
$iLastComponentType = CalcFunction::T_OPERATOR;
588+
} else {
589+
throw new UnexpectedTokenException(sprintf('Next token was expected to be an operand of type %s. Instead "%s" was found.', implode(', ', $aOperators), $oVal), '', 'custom', $this->iLineNo);
590+
}
586591
}
587592
}
588593
$oList->addListComponent($oCalcList);

tests/Sabberworm/CSS/ParserTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ function testUrlInFile() {
390390
function testCalcInFile() {
391391
$oDoc = $this->parsedStructureForFile('calc', Settings::create()->withMultibyteSupport(true));
392392
$sExpected = 'div {width: calc(100% / 4);}
393+
div {margin-top: calc(-120% - 4px);}
393394
div {height: -webkit-calc(9 / 16 * 100%) !important;width: -moz-calc(( 50px - 50% ) * 2);}';
394395
$this->assertSame($sExpected, $oDoc->render());
395396
}

tests/files/calc.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
div { width: calc(100% / 4); }
2+
div { margin-top: calc(-120% - 4px); }
23
div {
34
height: -webkit-calc(9/16 * 100%)!important;
45
width: -moz-calc((50px - 50%)*2);

0 commit comments

Comments
 (0)