Skip to content

Commit 3feb3ff

Browse files
author
petkodimitrov
committed
Resolve conflicts
2 parents 3c0e526 + 5d9902b commit 3feb3ff

20 files changed

+351
-71
lines changed

src/CSSList/CSSList.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ private static function parseListItem(ParserState $oParserState, CSSList $oList)
131131
} elseif ($oParserState->comes('}')) {
132132
if ($bIsRoot) {
133133
if ($oParserState->getSettings()->bLenientParsing) {
134-
return DeclarationBlock::parse($oParserState);
134+
$oParserState->bufferForSelector(1);
135+
return false;
135136
} else {
136137
throw new SourceException('Unopened {', $oParserState->currentLine());
137138
}

src/Parsing/ParserState.php

Lines changed: 107 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class ParserState
5050
* @var int
5151
*/
5252
private $iLineNo;
53+
private $sSelectorBuffer;
5354

5455
/**
5556
* @param string $sText the complete CSS as text (i.e., usually the contents of a CSS file)
@@ -62,6 +63,7 @@ public function __construct($sText, Settings $oParserSettings, $iLineNo = 1)
6263
$this->iCurrentPosition = 0;
6364
$this->iLineNo = $iLineNo;
6465
$this->setCharset($this->oParserSettings->sDefaultCharset);
66+
$this->sSelectorBuffer = "";
6567
}
6668

6769
/**
@@ -126,6 +128,26 @@ public function setPosition($iPosition): void
126128
$this->iCurrentPosition = $iPosition;
127129
}
128130

131+
/**
132+
* @param int $iCount
133+
*
134+
* @return void
135+
*/
136+
public function bufferForSelector($iCount)
137+
{
138+
$this->sSelectorBuffer .= $this->consume($iCount);
139+
}
140+
141+
/**
142+
* @return string
143+
*/
144+
public function consumeSelectorBuffer()
145+
{
146+
$sResult = $this->sSelectorBuffer;
147+
$this->sSelectorBuffer = "";
148+
return $sResult;
149+
}
150+
129151
/**
130152
* @param bool $bIgnoreCase
131153
*
@@ -166,7 +188,8 @@ public function parseIdentifier($bIgnoreCase = true)
166188
*/
167189
public function parseCharacter($bIsForIdentifier)
168190
{
169-
if ($this->peek() === '\\') {
191+
$sPeekChar = $this->peek();
192+
if ($sPeekChar === '\\') {
170193
if (
171194
$bIsForIdentifier && $this->oParserSettings->bLenientParsing
172195
&& ($this->comes('\\0') || $this->comes('\\9'))
@@ -200,22 +223,25 @@ public function parseCharacter($bIsForIdentifier)
200223
}
201224
return \iconv('utf-32le', $this->sCharset, $sUtf32);
202225
}
203-
if ($bIsForIdentifier) {
204-
$peek = \ord($this->peek());
205-
// Ranges: a-z A-Z 0-9 - _
206-
if (
207-
($peek >= 97 && $peek <= 122)
208-
|| ($peek >= 65 && $peek <= 90)
209-
|| ($peek >= 48 && $peek <= 57)
210-
|| ($peek === 45)
211-
|| ($peek === 95)
212-
|| ($peek > 0xa1)
213-
) {
214-
return $this->consume(1);
215-
}
216-
} else {
226+
227+
if (!$bIsForIdentifier) {
217228
return $this->consume(1);
218229
}
230+
231+
$peek = \ord($sPeekChar);
232+
// Ranges: a-z A-Z 0-9 - _
233+
//if (\preg_match('/[a-zA-Z0-9\-_]/', $sPeekChar) || \ord($sPeekChar) > 0xa1) {
234+
if (
235+
($peek >= 97 && $peek <= 122)
236+
|| ($peek >= 65 && $peek <= 90)
237+
|| ($peek >= 48 && $peek <= 57)
238+
|| ($peek === 45)
239+
|| ($peek === 95)
240+
|| ($peek > 0xa1)
241+
) {
242+
return $this->consume(1);
243+
}
244+
219245
return null;
220246
}
221247

@@ -232,15 +258,19 @@ public function consumeWhiteSpace(): array
232258
while (\preg_match('/\\s/isSu', $this->peek()) === 1) {
233259
$this->consume(1);
234260
}
235-
if ($this->oParserSettings->bLenientParsing) {
236-
try {
261+
262+
$oComment = false;
263+
if ($this->peek(1) == '/' && $this->peek(1, 1) == '*') {
264+
if ($this->oParserSettings->bLenientParsing) {
265+
try {
266+
$oComment = $this->consumeComment();
267+
} catch (UnexpectedEOFException $e) {
268+
$this->iCurrentPosition = $this->iLength;
269+
return $aComments;
270+
}
271+
} else {
237272
$oComment = $this->consumeComment();
238-
} catch (UnexpectedEOFException $e) {
239-
$this->iCurrentPosition = $this->iLength;
240-
return $aComments;
241273
}
242-
} else {
243-
$oComment = $this->consumeComment();
244274
}
245275
if ($oComment !== false) {
246276
$aComments[] = $oComment;
@@ -255,7 +285,17 @@ public function consumeWhiteSpace(): array
255285
*/
256286
public function comes($sString, $bCaseInsensitive = false): bool
257287
{
258-
$sPeek = $this->peek(\strlen($sString));
288+
if (!$sString) return false;
289+
290+
$sPeek1 = $this->peek();
291+
if ($bCaseInsensitive) {
292+
if (\strtolower($sPeek1) !== \strtolower($sString[0])) return false;
293+
} else {
294+
if ($sPeek1 !== $sString[0]) return false;
295+
}
296+
297+
$sPeek = \strlen($sString) == 1 ? $sPeek1 : $this->peek(\strlen($sString));
298+
259299
return ($sPeek == '')
260300
? false
261301
: $this->streql($sPeek, $sString, $bCaseInsensitive);
@@ -271,7 +311,12 @@ public function peek($iLength = 1, $iOffset = 0): string
271311
if ($iOffset >= $this->iLength) {
272312
return '';
273313
}
274-
return $this->substr($iOffset, $iLength);
314+
315+
if ($iLength == 1 && $iOffset + 1 <= $this->iLength) {
316+
return $this->aText[$iOffset];
317+
} else {
318+
return $this->substr($iOffset, $iLength);
319+
}
275320
}
276321

277322
/**
@@ -283,19 +328,24 @@ public function peek($iLength = 1, $iOffset = 0): string
283328
public function consume($mValue = 1): string
284329
{
285330
if (\is_string($mValue)) {
286-
$iLineCount = \substr_count($mValue, "\n");
287331
$iLength = $this->strlen($mValue);
288332
if (!$this->streql($this->substr($this->iCurrentPosition, $iLength), $mValue)) {
289333
throw new UnexpectedTokenException($mValue, $this->peek(\max($iLength, 5)), $this->iLineNo);
290334
}
291-
$this->iLineNo += $iLineCount;
335+
$this->iLineNo += \substr_count($mValue, "\n");
292336
$this->iCurrentPosition += $this->strlen($mValue);
293337
return $mValue;
294338
} else {
295339
if ($this->iCurrentPosition + $mValue > $this->iLength) {
296340
throw new UnexpectedEOFException($mValue, $this->peek(5), 'count', $this->iLineNo);
297341
}
298-
$sResult = $this->substr($this->iCurrentPosition, $mValue);
342+
343+
if ($mValue == 1 && $this->iCurrentPosition + 1 <= $this->iLength) {
344+
$sResult = $this->aText[$this->iCurrentPosition];
345+
} else {
346+
$sResult = $this->substr($this->iCurrentPosition, $mValue);
347+
}
348+
299349
$iLineCount = \substr_count($sResult, "\n");
300350
$this->iLineNo += $iLineCount;
301351
$this->iCurrentPosition += $mValue;
@@ -325,26 +375,27 @@ public function consumeExpression($mExpression, $iMaxLength = null): string
325375
*/
326376
public function consumeComment()
327377
{
328-
$mComment = false;
329-
if ($this->comes('/*')) {
330-
$iLineNo = $this->iLineNo;
331-
$this->consume(1);
332-
$mComment = '';
333-
while (($char = $this->consume(1)) !== '') {
334-
$mComment .= $char;
335-
if ($this->comes('*/')) {
336-
$this->consume(2);
337-
break;
338-
}
378+
if ($this->peek() != '/' || $this->peek(1, 1) != '*') {
379+
return false;
380+
}
381+
382+
$sComment = '';
383+
$iLineNo = $this->iLineNo;
384+
$this->consume(1);
385+
while (($char = $this->consume(1)) !== '') {
386+
if ($char == '*' && $this->peek() == '/') {
387+
$this->consume(1);
388+
break;
339389
}
390+
$sComment .= $char;
340391
}
341392

342-
if ($mComment !== false) {
393+
if ($sComment !== '') {
343394
// We skip the * which was included in the comment.
344-
return new Comment(\substr($mComment, 1), $iLineNo);
395+
return new Comment(\substr($sComment, 1), $iLineNo);
345396
}
346397

347-
return $mComment;
398+
return false;
348399
}
349400

350401
public function isEnd(): bool
@@ -380,8 +431,10 @@ public function consumeUntil($aEnd, $bIncludeEnd = false, $consumeEnd = false, a
380431
return $out;
381432
}
382433
$out .= $char;
383-
if ($comment = $this->consumeComment()) {
384-
$comments[] = $comment;
434+
if ($this->peek(1) == '/' && $this->peek(1, 1) == '*') {
435+
if ($comment = $this->consumeComment()) {
436+
$comments[] = $comment;
437+
}
385438
}
386439
}
387440

@@ -479,7 +532,17 @@ private function strsplit($sString)
479532
{
480533
if ($this->oParserSettings->bMultibyteSupport) {
481534
if ($this->streql($this->sCharset, 'utf-8')) {
482-
return \preg_split('//u', $sString, -1, PREG_SPLIT_NO_EMPTY);
535+
$iLimit = 1024 * 1024;
536+
$iLength = \mb_strlen($sString, $this->sCharset);
537+
$iOffset = 0;
538+
$aResult = [];
539+
for ($iOffset = 0; $iOffset < $iLength; $iOffset += $iLimit) {
540+
$sChunk = \mb_substr($sString, $iOffset, $iLimit, 'utf-8');
541+
foreach (\preg_split('//u', $sChunk, -1, PREG_SPLIT_NO_EMPTY) as $sChar) {
542+
$aResult[] = $sChar;
543+
}
544+
}
545+
return $aResult;
483546
} else {
484547
$iLength = \mb_strlen($sString, $this->sCharset);
485548
$aResult = [];

src/Property/Charset.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function setCharset($sCharset): void
6666
*/
6767
public function getCharset()
6868
{
69-
return $this->oCharset->getString();
69+
return preg_replace('/;$/', '', $this->oCharset->getString());
7070
}
7171

7272
public function __toString(): string

src/Property/Selector.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Selector
4646
/ix';
4747

4848
/**
49-
* regexp for specificity calculations
49+
* regexp for validity verifications
5050
*
5151
* @var string
5252
*
@@ -79,7 +79,7 @@ class Selector
7979
*/
8080
public static function isValid($sSelector)
8181
{
82-
return \preg_match(static::SELECTOR_VALIDATION_RX, $sSelector);
82+
return \preg_match(static::SELECTOR_VALIDATION_RX, $sSelector) && \strpos($sSelector, ': ') === false;
8383
}
8484

8585
/**

src/Rule/Rule.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,21 @@ public static function parse(ParserState $oParserState): Rule
8989
$oRule->setValue($oValue);
9090
if ($oParserState->getSettings()->bLenientParsing) {
9191
while ($oParserState->comes('\\')) {
92-
$oParserState->consume('\\');
92+
$oParserState->consume(1);
9393
$oRule->addIeHack($oParserState->consume());
9494
$oParserState->consumeWhiteSpace();
9595
}
9696
}
9797
$oParserState->consumeWhiteSpace();
98-
if ($oParserState->comes('!')) {
99-
$oParserState->consume('!');
98+
if ($oParserState->peek() == '!') {
99+
$oParserState->consume(1);
100100
$oParserState->consumeWhiteSpace();
101101
$oParserState->consume('important');
102102
$oRule->setIsImportant(true);
103103
}
104104
$oParserState->consumeWhiteSpace();
105-
while ($oParserState->comes(';')) {
106-
$oParserState->consume(';');
105+
while ($oParserState->peek() == ';') {
106+
$oParserState->consume(1);
107107
}
108108
$oParserState->consumeWhiteSpace();
109109

src/RuleSet/DeclarationBlock.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public static function parse(ParserState $oParserState, $oList = null)
5656
$oResult = new DeclarationBlock($oParserState->currentLine());
5757
try {
5858
$aSelectorParts = [];
59+
$sSelectorBuffer = $oParserState->consumeSelectorBuffer();
60+
if ($sSelectorBuffer) {
61+
$aSelectorParts[] = $sSelectorBuffer;
62+
}
5963
$sStringWrapperChar = false;
6064
do {
6165
$aSelectorParts[] = $oParserState->consume(1)

src/RuleSet/RuleSet.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ public static function parseRuleSet(ParserState $oParserState, RuleSet $oRuleSet
6363
$oRule = Rule::parse($oParserState);
6464
} catch (UnexpectedTokenException $e) {
6565
try {
66-
$sConsume = $oParserState->consumeUntil(["\n", ';', '}'], true);
66+
$sConsume = $oParserState->consumeUntil(["\n", ";", '{', '}'], true);
6767
// We need to “unfind” the matches to the end of the ruleSet as this will be matched later
68-
if ($oParserState->streql(\substr($sConsume, -1), '}')) {
68+
if ($oParserState->streql(substr($sConsume, -1), '{')) { // We need to skip the entire block
69+
$oParserState->consumeUntil('}', true);
70+
} elseif ($oParserState->streql(substr($sConsume, -1), '}')) {
6971
$oParserState->backtrack(1);
7072
} else {
7173
while ($oParserState->comes(';')) {

src/Value/CSSFunction.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ private static function parseName(ParserState $oParserState, bool $bIgnoreCase =
6767
* @throws UnexpectedEOFException
6868
* @throws UnexpectedTokenException
6969
*/
70-
private static function parseArguments(ParserState $oParserState)
70+
protected static function parseArguments(ParserState $oParserState)
7171
{
7272
return Value::parseValue($oParserState, ['=', ' ', ',']);
7373
}

0 commit comments

Comments
 (0)