Skip to content

Commit 425c78e

Browse files
committed
Improvement: Handle escaped characters when validating selectors
1 parent 5b3f780 commit 425c78e

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

lib/Sabberworm/CSS/Property/Selector.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,20 @@ class Selector {
3737
))
3838
/ix';
3939

40+
const SELECTOR_VALIDATION_RX = '/
41+
^((?:[a-zA-Z0-9\x{00A0}-\x{FFFF}_\^\$\|\*\=\"\'\~\[\]\(\)\-\s\.:#\+\>]*(?:\\\\.)?)*|\s*?[\+-]?\d+\%\s*)$
42+
/ux';
43+
4044
private $sSelector;
4145
private $iSpecificity;
4246

4347
public static function isValid($sSelector) {
44-
return preg_match("/^([a-zA-Z0-9\x{00A0}-\x{FFFF}_\^\$\|\*\=\"\'\~\[\]\(\)\-\s\.:#\+\>]*|\s*?[\+-]?\d+\%\s*)$/u", $sSelector);
48+
return preg_match(self::SELECTOR_VALIDATION_RX, $sSelector);
4549
}
4650

4751
public function __construct($sSelector, $bCalculateSpecificity = false) {
4852
if (!Selector::isValid($sSelector)) {
49-
throw new UnexpectedTokenException("Selector did not match '/^([a-zA-Z0-9\x{00A0}-\x{FFFF}_\^\$\|\*\=\"\'\~\[\]\(\)\-\s\.:#\+\>]*|\s*?[\+-]?\d+\%\s*)$/u'.", $sSelector, "custom");
53+
throw new UnexpectedTokenException("Selector did not match '{self::SELECTOR_VALIDATION_RX}'.", $sSelector, "custom");
5054
}
5155
$this->setSelector($sSelector);
5256
if ($bCalculateSpecificity) {

tests/Sabberworm/CSS/ParserTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,22 @@ function testInvalidSelectorsInFile() {
449449
$this->assertSame($sExpected, $oDoc->render());
450450
}
451451

452+
function testSelectorEscapesInFile() {
453+
$oDoc = $this->parsedStructureForFile('selector-escapes', Settings::create()->withMultibyteSupport(true));
454+
$sExpected = '#\# {color: red;}
455+
.col-sm-1\/5 {width: 20%;}';
456+
$this->assertSame($sExpected, $oDoc->render());
457+
458+
$oDoc = $this->parsedStructureForFile('invalid-selectors-2', Settings::create()->withMultibyteSupport(true));
459+
$sExpected = '@media only screen and (max-width: 1215px) {.breadcrumb {padding-left: 10px;}
460+
.super-menu > li:first-of-type {border-left-width: 0;}
461+
.super-menu > li:last-of-type {border-right-width: 0;}
462+
html[dir="rtl"] .super-menu > li:first-of-type {border-left-width: 1px;border-right-width: 0;}
463+
html[dir="rtl"] .super-menu > li:last-of-type {border-left-width: 0;}}
464+
body {background-color: red;}';
465+
$this->assertSame($sExpected, $oDoc->render());
466+
}
467+
452468
/**
453469
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
454470
*/

tests/files/selector-escapes.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#\# {
2+
color: red;
3+
}
4+
5+
.col-sm-1\/5 {
6+
width: 20%;
7+
}

0 commit comments

Comments
 (0)