Skip to content

Commit e1ecb78

Browse files
author
Frederic Massart
committed
Support for IE hack parsing in lenient mode
This allows for \0 and \9 to remain as they are intended. And will throw an exception when they are found in strict mode.
1 parent dcfbc81 commit e1ecb78

File tree

4 files changed

+52
-1
lines changed

4 files changed

+52
-1
lines changed

lib/Sabberworm/CSS/Parser.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ private function parseStringValue() {
255255

256256
private function parseCharacter($bIsForIdentifier) {
257257
if ($this->peek() === '\\') {
258+
if ($bIsForIdentifier && $this->oParserSettings->bLenientParsing && ($this->comes('\0') || $this->comes('\9'))) {
259+
// Non-strings can contain \0 or \9 which is an IE hack supported in lenient parsing.
260+
return null;
261+
}
258262
$this->consume('\\');
259263
if ($this->comes('\n') || $this->comes('\r')) {
260264
return '';
@@ -350,6 +354,13 @@ private function parseRule() {
350354
$this->consume(':');
351355
$oValue = $this->parseValue(self::listDelimiterForRule($oRule->getRule()));
352356
$oRule->setValue($oValue);
357+
if ($this->oParserSettings->bLenientParsing) {
358+
while ($this->comes('\\')) {
359+
$this->consume('\\');
360+
$oRule->addIeHack($this->consume());
361+
$this->consumeWhiteSpace();
362+
}
363+
}
353364
if ($this->comes('!')) {
354365
$this->consume('!');
355366
$this->consumeWhiteSpace();
@@ -367,7 +378,7 @@ private function parseValue($aListDelimiters) {
367378
$aStack = array();
368379
$this->consumeWhiteSpace();
369380
//Build a list of delimiters and parsed values
370-
while (!($this->comes('}') || $this->comes(';') || $this->comes('!') || $this->comes(')'))) {
381+
while (!($this->comes('}') || $this->comes(';') || $this->comes('!') || $this->comes(')') || $this->comes('\\'))) {
371382
if (count($aStack) > 0) {
372383
$bFoundDelimiter = false;
373384
foreach ($aListDelimiters as $sDelimiter) {

lib/Sabberworm/CSS/Rule/Rule.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ class Rule implements Renderable {
1515
private $sRule;
1616
private $mValue;
1717
private $bIsImportant;
18+
private $aIeHack;
1819
protected $iLineNo;
1920

2021
public function __construct($sRule, $iLineNo = 0) {
2122
$this->sRule = $sRule;
2223
$this->mValue = null;
2324
$this->bIsImportant = false;
25+
$this->aIeHack = array();
2426
$this->iLineNo = $iLineNo;
2527
}
2628

@@ -127,6 +129,18 @@ public function addValue($mValue, $sType = ' ') {
127129
}
128130
}
129131

132+
public function addIeHack($iModifier) {
133+
$this->aIeHack[] = $iModifier;
134+
}
135+
136+
public function setIeHack(array $aModifiers) {
137+
$this->aIeHack = $aModifiers;
138+
}
139+
140+
public function getIeHack() {
141+
return $this->aIeHack;
142+
}
143+
130144
public function setIsImportant($bIsImportant) {
131145
$this->bIsImportant = $bIsImportant;
132146
}
@@ -146,6 +160,9 @@ public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
146160
} else {
147161
$sResult .= $this->mValue;
148162
}
163+
if (!empty($this->aIeHack)) {
164+
$sResult .= ' \\' . implode('\\', $this->aIeHack);
165+
}
149166
if ($this->bIsImportant) {
150167
$sResult .= ' !important';
151168
}

tests/Sabberworm/CSS/ParserTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,4 +505,18 @@ function testUnexpectedTokenExceptionLineNo() {
505505
throw $e;
506506
}
507507
}
508+
509+
/**
510+
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
511+
*/
512+
function testIeHacksStrictParsing() {
513+
// We can't strictly parse IE hacks.
514+
$this->parsedStructureForFile('ie-hacks', Settings::create()->beStrict());
515+
}
516+
517+
function testIeHacksParsing() {
518+
$oDoc = $this->parsedStructureForFile('ie-hacks', Settings::create()->withLenientParsing(true));
519+
$sExpected = 'p {padding-right: .75rem \9;background-image: none \9;color: red \9\0;background-color: red \9\0;background-color: red \9\0 !important;content: "red \0";content: "red઼";}';
520+
$this->assertEquals($sExpected, $oDoc->render());
521+
}
508522
}

tests/files/ie-hacks.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
p {
2+
padding-right: .75rem \9;
3+
background-image: none \9;
4+
color:red\9\0;
5+
background-color:red \9 \0;
6+
background-color:red \9 \0 !important;
7+
content: "red \9\0";
8+
content: "red\0abc";
9+
}

0 commit comments

Comments
 (0)