%PDF- %PDF-
| Direktori : /home/q/g/b/qgbqkvz/www/wp-content/plugins/wp-scss/scssphp/src/Parser/ |
| Current File : /home/q/g/b/qgbqkvz/www/wp-content/plugins/wp-scss/scssphp/src/Parser/MediaQueryParser.php |
<?php
/**
* SCSSPHP
*
* @copyright 2012-2020 Leaf Corcoran
*
* @license http://opensource.org/licenses/MIT MIT
*
* @link http://scssphp.github.io/scssphp
*/
namespace ScssPhp\ScssPhp\Parser;
use ScssPhp\ScssPhp\Ast\Css\CssMediaQuery;
use ScssPhp\ScssPhp\Exception\SassFormatException;
/**
* A parser for `@media` queries.
*
* @internal
*/
final class MediaQueryParser extends Parser
{
/**
* @return list<CssMediaQuery>
*
* @throws SassFormatException when parsing fails
*/
public function parse(): array
{
try {
$queries = [];
do {
$this->whitespace();
$queries[] = $this->mediaQuery();
$this->whitespace();
} while ($this->scanner->scanChar(','));
$this->scanner->expectDone();
return $queries;
} catch (FormatException $e) {
throw $this->wrapException($e);
}
}
/**
* Consumes a single media query.
*/
private function mediaQuery(): CssMediaQuery
{
if ($this->scanner->peekChar() === '(') {
$conditions = [$this->mediaInParens()];
$this->whitespace();
$conjunction = true;
if ($this->scanIdentifier('and')) {
$this->expectWhitespace();
$conditions = array_merge($conditions, $this->mediaLogicSequence('and'));
} elseif ($this->scanIdentifier('or')) {
$this->expectWhitespace();
$conjunction = false;
$conditions = array_merge($conditions, $this->mediaLogicSequence('or'));
}
return CssMediaQuery::condition($conditions, $conjunction);
}
$modifier = null;
$type = null;
$identifier1 = $this->identifier();
if (strtolower($identifier1) === 'not') {
$this->expectWhitespace();
if (!$this->lookingAtIdentifier()) {
// For example, "@media not (...) {"
return CssMediaQuery::condition(['(not ' . $this->mediaInParens() . ')']);
}
}
$this->whitespace();
if (!$this->lookingAtIdentifier()) {
// For example, "@media screen {"
return CssMediaQuery::type($identifier1);
}
$identifier2 = $this->identifier();
if (strtolower($identifier2) === 'and') {
$this->expectWhitespace();
// For example, "@media screen and ..."
$type = $identifier1;
} else {
$this->whitespace();
$modifier = $identifier1;
$type = $identifier2;
if ($this->scanIdentifier('and')) {
// For example, "@media only screen and ..."
$this->expectWhitespace();
} else {
// For example, "@media only screen {"
return CssMediaQuery::type($type, $modifier);
}
}
// We've consumed either `IDENTIFIER "and"` or
// `IDENTIFIER IDENTIFIER "and"`.
if ($this->scanIdentifier('not')) {
// For example, "@media screen and not (...) {"
return CssMediaQuery::type($type, $modifier, ['(not ' . $this->mediaInParens() . ')']);
}
return CssMediaQuery::type($type, $modifier, $this->mediaLogicSequence('and'));
}
/**
* Consumes one or more `<media-in-parens>` expressions separated by
* $operator and returns them.
*
* @return list<string>
*/
private function mediaLogicSequence(string $operator): array
{
$result = [];
while (true) {
$result[] = $this->mediaInParens();
$this->whitespace();
if (!$this->scanIdentifier($operator)) {
return $result;
}
$this->expectWhitespace();
}
}
/**
* Consumes a `<media-in-parens>` expression and returns it, parentheses
* included.
*/
private function mediaInParens(): string
{
$this->scanner->expectChar('(', 'media condition in parentheses');
$result = '(' . $this->declarationValue() . ')';
$this->scanner->expectChar(')');
return $result;
}
}