diff --git a/lib/Sabberworm/CSS/Value/Size.php b/lib/Sabberworm/CSS/Value/Size.php index 8490cc35..cd1a213c 100644 --- a/lib/Sabberworm/CSS/Value/Size.php +++ b/lib/Sabberworm/CSS/Value/Size.php @@ -3,12 +3,13 @@ namespace Sabberworm\CSS\Value; use Sabberworm\CSS\Parsing\ParserState; +use Sabberworm\CSS\Parsing\UnexpectedTokenException; class Size extends PrimitiveValue { const ABSOLUTE_SIZE_UNITS = 'px/cm/mm/mozmm/in/pt/pc/vh/vw/vmin/vmax/rem'; //vh/vw/vm(ax)/vmin/rem are absolute insofar as they don’t scale to the immediate parent (only the viewport) const RELATIVE_SIZE_UNITS = '%/em/ex/ch/fr'; - const NON_SIZE_UNITS = 'deg/grad/rad/s/ms/turns/Hz/kHz'; + const NON_SIZE_UNITS = 'deg/grad/rad/s/ms/turn/Hz/kHz'; private static $SIZE_UNITS = null; @@ -38,15 +39,20 @@ public static function parse(ParserState $oParserState, $bIsColorComponent = fal $sUnit = null; $aSizeUnits = self::getSizeUnits(); - foreach($aSizeUnits as $iLength => &$aValues) { - $sKey = strtolower($oParserState->peek($iLength)); - if(array_key_exists($sKey, $aValues)) { - if (($sUnit = $aValues[$sKey]) !== null) { - $oParserState->consume($iLength); - break; - } + $iMaxSizeUnitLength = max(array_keys($aSizeUnits)); + + if ( preg_match( '/^(%|[a-zA-Z0-9]+)/', $oParserState->peek($iMaxSizeUnitLength), $matches ) ) { + $sUnit = strtolower($matches[0]); + $iUnitLength = strlen($sUnit); + + if (isset($aSizeUnits[$iUnitLength][$sUnit])) { + $sUnit = $aSizeUnits[$iUnitLength][$sUnit]; + $oParserState->consume($iUnitLength); + } else { + throw new UnexpectedTokenException('Unit', $sUnit, 'identifier', $oParserState->currentLine()); } } + return new Size(floatval($sSize), $sUnit, $bIsColorComponent, $oParserState->currentLine()); } diff --git a/tests/Sabberworm/CSS/ParserTest.php b/tests/Sabberworm/CSS/ParserTest.php index 4a690196..6ef74bbb 100644 --- a/tests/Sabberworm/CSS/ParserTest.php +++ b/tests/Sabberworm/CSS/ParserTest.php @@ -787,4 +787,22 @@ function testLonelyImport() { $sExpected = "@import url(\"example.css\") only screen and (max-width: 600px);"; $this->assertSame($sExpected, $oDoc->render()); } + + function testTurnUnitLenient() { + $sText = ".foo {transform: rotate(1turn);}\n.bar {transform: rotate(1turns);}"; + $sExpected = ".foo {transform: rotate(1turn);}\n.bar {}"; + + $oParser = new Parser($sText); + $this->assertSame($sExpected, $oParser->parse()->render()); + } + + function testTurnUnitStrict() { + $sText = ".foo {transform: rotate(1turn);}\n.bar {transform: rotate(1turns);}"; + + $oParser = new Parser($sText, Settings::create()->beStrict()); + + // Line 2 contains the invalid unit and so should be reported. + $this->setExpectedException( 'Sabberworm\CSS\Parsing\UnexpectedTokenException', 'Identifier expected. Got “turns” [line no: 2]' ); + $oParser->parse(); + } }