Skip to content

Commit

Permalink
[FEATURE] Support arithmetic operators in CSS functions (#624)
Browse files Browse the repository at this point in the history
This is the enhancement from #390.

`calc` was already supported.

Co-authored-by: Jake Hotson <[email protected]>
  • Loading branch information
JakeQZ and Jake Hotson authored Jun 30, 2024
1 parent 9b91918 commit ba37b45
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
## x.y.z

### Added
- Support arithmetic operators in CSS function arguments (#607)
- Add support for inserting an item in a CSS list (#545)

- Add support for the `dvh`, `lvh` and `svh` length units (#415)

### Changed
Expand Down
11 changes: 10 additions & 1 deletion src/Value/Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,16 @@ public static function parsePrimitiveValue(ParserState $oParserState)
} elseif ($oParserState->comes("U+")) {
$oValue = self::parseUnicodeRangeValue($oParserState);
} else {
$oValue = self::parseIdentifierOrFunction($oParserState);
$sNextChar = $oParserState->peek(1);
try {
$oValue = self::parseIdentifierOrFunction($oParserState);
} catch (UnexpectedTokenException $e) {
if (\in_array($sNextChar, ['+', '-', '*', '/'], true)) {
$oValue = $oParserState->consume(1);
} else {
throw $e;
}
}
}
$oParserState->consumeWhiteSpace();
return $oValue;
Expand Down
107 changes: 107 additions & 0 deletions tests/Value/ValueTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace Sabberworm\CSS\Tests\Value;

use PHPUnit\Framework\TestCase;
use Sabberworm\CSS\Parsing\ParserState;
use Sabberworm\CSS\Settings;
use Sabberworm\CSS\Value\Value;

/**
* @covers \Sabberworm\CSS\Value\Value
*/
final class ValueTest extends TestCase
{
/**
* @return array<string, array{0: string}>
*/
public static function provideArithmeticOperator()
{
$units = ['+', '-', '*', '/'];

return \array_combine(
$units,
\array_map(
function ($unit) {
return [$unit];
},
$units
)
);
}

/**
* @test
*
* @dataProvider provideArithmeticOperator
*/
public function parsesArithmeticInFunctions($operator)
{
$subject = Value::parseValue(new ParserState('max(300px, 50vh ' . $operator . ' 10px);', Settings::create()));

self::assertSame('max(300px,50vh ' . $operator . ' 10px)', (string) $subject);
}

/**
* @return array<string, array{0: string, 1: string}>
* The first datum is a template for the parser (using `sprintf` insertion marker `%s` for some expression).
* The second is for the expected result, which may have whitespace and trailing semicolon removed.
*/
public static function provideCssFunctionTemplates()
{
return [
'calc' => [
'to be parsed' => 'calc(%s);',
'expected' => 'calc(%s)',
],
'max' => [
'to be parsed' => 'max(300px, %s);',
'expected' => 'max(300px,%s)',
],
];
}

/**
* @test
*
* @dataProvider provideCssFunctionTemplates
*/
public function parsesArithmeticWithMultipleOperatorsInFunctions(
$parserTemplate,
$expectedResultTemplate
) {
static $expression = '300px + 10% + 10vw';

$subject = Value::parseValue(new ParserState(\sprintf($parserTemplate, $expression), Settings::create()));

self::assertSame(\sprintf($expectedResultTemplate, $expression), (string) $subject);
}

/**
* @return array<string, array{0: string, 1: string}>
*/
public static function provideMalformedLengthOperands()
{
return [
'LHS missing number' => ['vh', '10px'],
'RHS missing number' => ['50vh', 'px'],
'LHS missing unit' => ['50', '10px'],
'RHS missing unit' => ['50vh', '10'],
];
}

/**
* @test
*
* @dataProvider provideMalformedLengthOperands
*/
public function parsesArithmeticWithMalformedOperandsInFunctions($leftOperand, $rightOperand)
{
$subject = Value::parseValue(new ParserState(
'max(300px, ' . $leftOperand . ' + ' . $rightOperand . ');',
Settings::create()
));

self::assertSame('max(300px,' . $leftOperand . ' + ' . $rightOperand . ')', (string) $subject);
}
}

0 comments on commit ba37b45

Please sign in to comment.