fixes
This commit is contained in:
83
vendor/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php
vendored
Normal file
83
vendor/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\OutputFormat;
|
||||
use Sabberworm\CSS\Property\AtRule;
|
||||
|
||||
/**
|
||||
* A `BlockList` constructed by an unknown at-rule. `@media` rules are rendered into `AtRuleBlockList` objects.
|
||||
*/
|
||||
class AtRuleBlockList extends CSSBlockList implements AtRule
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sType;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sArgs;
|
||||
|
||||
/**
|
||||
* @param string $sType
|
||||
* @param string $sArgs
|
||||
* @param int $iLineNo
|
||||
*/
|
||||
public function __construct($sType, $sArgs = '', $iLineNo = 0)
|
||||
{
|
||||
parent::__construct($iLineNo);
|
||||
$this->sType = $sType;
|
||||
$this->sArgs = $sArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function atRuleName()
|
||||
{
|
||||
return $this->sType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function atRuleArgs()
|
||||
{
|
||||
return $this->sArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->render(new OutputFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render(OutputFormat $oOutputFormat)
|
||||
{
|
||||
$sArgs = $this->sArgs;
|
||||
if ($sArgs) {
|
||||
$sArgs = ' ' . $sArgs;
|
||||
}
|
||||
$sResult = $oOutputFormat->sBeforeAtRuleBlock;
|
||||
$sResult .= "@{$this->sType}$sArgs{$oOutputFormat->spaceBeforeOpeningBrace()}{";
|
||||
$sResult .= parent::render($oOutputFormat);
|
||||
$sResult .= '}';
|
||||
$sResult .= $oOutputFormat->sAfterAtRuleBlock;
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isRootList()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
143
vendor/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php
vendored
Normal file
143
vendor/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\Property\Selector;
|
||||
use Sabberworm\CSS\Rule\Rule;
|
||||
use Sabberworm\CSS\RuleSet\DeclarationBlock;
|
||||
use Sabberworm\CSS\RuleSet\RuleSet;
|
||||
use Sabberworm\CSS\Value\CSSFunction;
|
||||
use Sabberworm\CSS\Value\Value;
|
||||
use Sabberworm\CSS\Value\ValueList;
|
||||
|
||||
/**
|
||||
* A `CSSBlockList` is a `CSSList` whose `DeclarationBlock`s are guaranteed to contain valid declaration blocks or
|
||||
* at-rules.
|
||||
*
|
||||
* Most `CSSList`s conform to this category but some at-rules (such as `@keyframes`) do not.
|
||||
*/
|
||||
abstract class CSSBlockList extends CSSList
|
||||
{
|
||||
/**
|
||||
* @param int $iLineNo
|
||||
*/
|
||||
public function __construct($iLineNo = 0)
|
||||
{
|
||||
parent::__construct($iLineNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, DeclarationBlock> $aResult
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function allDeclarationBlocks(array &$aResult)
|
||||
{
|
||||
foreach ($this->aContents as $mContent) {
|
||||
if ($mContent instanceof DeclarationBlock) {
|
||||
$aResult[] = $mContent;
|
||||
} elseif ($mContent instanceof CSSBlockList) {
|
||||
$mContent->allDeclarationBlocks($aResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, RuleSet> $aResult
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function allRuleSets(array &$aResult)
|
||||
{
|
||||
foreach ($this->aContents as $mContent) {
|
||||
if ($mContent instanceof RuleSet) {
|
||||
$aResult[] = $mContent;
|
||||
} elseif ($mContent instanceof CSSBlockList) {
|
||||
$mContent->allRuleSets($aResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CSSList|Rule|RuleSet|Value $oElement
|
||||
* @param array<int, Value> $aResult
|
||||
* @param string|null $sSearchString
|
||||
* @param bool $bSearchInFunctionArguments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function allValues($oElement, array &$aResult, $sSearchString = null, $bSearchInFunctionArguments = false)
|
||||
{
|
||||
if ($oElement instanceof CSSBlockList) {
|
||||
foreach ($oElement->getContents() as $oContent) {
|
||||
$this->allValues($oContent, $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
}
|
||||
} elseif ($oElement instanceof RuleSet) {
|
||||
foreach ($oElement->getRules($sSearchString) as $oRule) {
|
||||
$this->allValues($oRule, $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
}
|
||||
} elseif ($oElement instanceof Rule) {
|
||||
$this->allValues($oElement->getValue(), $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
} elseif ($oElement instanceof ValueList) {
|
||||
if ($bSearchInFunctionArguments || !($oElement instanceof CSSFunction)) {
|
||||
foreach ($oElement->getListComponents() as $mComponent) {
|
||||
$this->allValues($mComponent, $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Non-List `Value` or `CSSString` (CSS identifier)
|
||||
$aResult[] = $oElement;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, Selector> $aResult
|
||||
* @param string|null $sSpecificitySearch
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function allSelectors(array &$aResult, $sSpecificitySearch = null)
|
||||
{
|
||||
/** @var array<int, DeclarationBlock> $aDeclarationBlocks */
|
||||
$aDeclarationBlocks = [];
|
||||
$this->allDeclarationBlocks($aDeclarationBlocks);
|
||||
foreach ($aDeclarationBlocks as $oBlock) {
|
||||
foreach ($oBlock->getSelectors() as $oSelector) {
|
||||
if ($sSpecificitySearch === null) {
|
||||
$aResult[] = $oSelector;
|
||||
} else {
|
||||
$sComparator = '===';
|
||||
$aSpecificitySearch = explode(' ', $sSpecificitySearch);
|
||||
$iTargetSpecificity = $aSpecificitySearch[0];
|
||||
if (count($aSpecificitySearch) > 1) {
|
||||
$sComparator = $aSpecificitySearch[0];
|
||||
$iTargetSpecificity = $aSpecificitySearch[1];
|
||||
}
|
||||
$iTargetSpecificity = (int)$iTargetSpecificity;
|
||||
$iSelectorSpecificity = $oSelector->getSpecificity();
|
||||
$bMatches = false;
|
||||
switch ($sComparator) {
|
||||
case '<=':
|
||||
$bMatches = $iSelectorSpecificity <= $iTargetSpecificity;
|
||||
break;
|
||||
case '<':
|
||||
$bMatches = $iSelectorSpecificity < $iTargetSpecificity;
|
||||
break;
|
||||
case '>=':
|
||||
$bMatches = $iSelectorSpecificity >= $iTargetSpecificity;
|
||||
break;
|
||||
case '>':
|
||||
$bMatches = $iSelectorSpecificity > $iTargetSpecificity;
|
||||
break;
|
||||
default:
|
||||
$bMatches = $iSelectorSpecificity === $iTargetSpecificity;
|
||||
break;
|
||||
}
|
||||
if ($bMatches) {
|
||||
$aResult[] = $oSelector;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
479
vendor/sabberworm/php-css-parser/src/CSSList/CSSList.php
vendored
Normal file
479
vendor/sabberworm/php-css-parser/src/CSSList/CSSList.php
vendored
Normal file
@@ -0,0 +1,479 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\Comment\Comment;
|
||||
use Sabberworm\CSS\Comment\Commentable;
|
||||
use Sabberworm\CSS\OutputFormat;
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\SourceException;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
|
||||
use Sabberworm\CSS\Property\AtRule;
|
||||
use Sabberworm\CSS\Property\Charset;
|
||||
use Sabberworm\CSS\Property\CSSNamespace;
|
||||
use Sabberworm\CSS\Property\Import;
|
||||
use Sabberworm\CSS\Property\Selector;
|
||||
use Sabberworm\CSS\Renderable;
|
||||
use Sabberworm\CSS\RuleSet\AtRuleSet;
|
||||
use Sabberworm\CSS\RuleSet\DeclarationBlock;
|
||||
use Sabberworm\CSS\RuleSet\RuleSet;
|
||||
use Sabberworm\CSS\Settings;
|
||||
use Sabberworm\CSS\Value\CSSString;
|
||||
use Sabberworm\CSS\Value\URL;
|
||||
use Sabberworm\CSS\Value\Value;
|
||||
|
||||
/**
|
||||
* A `CSSList` is the most generic container available. Its contents include `RuleSet` as well as other `CSSList`
|
||||
* objects.
|
||||
*
|
||||
* Also, it may contain `Import` and `Charset` objects stemming from at-rules.
|
||||
*/
|
||||
abstract class CSSList implements Renderable, Commentable
|
||||
{
|
||||
/**
|
||||
* @var array<array-key, Comment>
|
||||
*/
|
||||
protected $aComments;
|
||||
|
||||
/**
|
||||
* @var array<int, RuleSet|CSSList|Import|Charset>
|
||||
*/
|
||||
protected $aContents;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $iLineNo;
|
||||
|
||||
/**
|
||||
* @param int $iLineNo
|
||||
*/
|
||||
public function __construct($iLineNo = 0)
|
||||
{
|
||||
$this->aComments = [];
|
||||
$this->aContents = [];
|
||||
$this->iLineNo = $iLineNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*
|
||||
* @throws UnexpectedTokenException
|
||||
* @throws SourceException
|
||||
*/
|
||||
public static function parseList(ParserState $oParserState, CSSList $oList)
|
||||
{
|
||||
$bIsRoot = $oList instanceof Document;
|
||||
if (is_string($oParserState)) {
|
||||
$oParserState = new ParserState($oParserState, Settings::create());
|
||||
}
|
||||
$bLenientParsing = $oParserState->getSettings()->bLenientParsing;
|
||||
while (!$oParserState->isEnd()) {
|
||||
$comments = $oParserState->consumeWhiteSpace();
|
||||
$oListItem = null;
|
||||
if ($bLenientParsing) {
|
||||
try {
|
||||
$oListItem = self::parseListItem($oParserState, $oList);
|
||||
} catch (UnexpectedTokenException $e) {
|
||||
$oListItem = false;
|
||||
}
|
||||
} else {
|
||||
$oListItem = self::parseListItem($oParserState, $oList);
|
||||
}
|
||||
if ($oListItem === null) {
|
||||
// List parsing finished
|
||||
return;
|
||||
}
|
||||
if ($oListItem) {
|
||||
$oListItem->setComments($comments);
|
||||
$oList->append($oListItem);
|
||||
}
|
||||
$oParserState->consumeWhiteSpace();
|
||||
}
|
||||
if (!$bIsRoot && !$bLenientParsing) {
|
||||
throw new SourceException("Unexpected end of document", $oParserState->currentLine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AtRuleBlockList|KeyFrame|Charset|CSSNamespace|Import|AtRuleSet|DeclarationBlock|null|false
|
||||
*
|
||||
* @throws SourceException
|
||||
* @throws UnexpectedEOFException
|
||||
* @throws UnexpectedTokenException
|
||||
*/
|
||||
private static function parseListItem(ParserState $oParserState, CSSList $oList)
|
||||
{
|
||||
$bIsRoot = $oList instanceof Document;
|
||||
if ($oParserState->comes('@')) {
|
||||
$oAtRule = self::parseAtRule($oParserState);
|
||||
if ($oAtRule instanceof Charset) {
|
||||
if (!$bIsRoot) {
|
||||
throw new UnexpectedTokenException(
|
||||
'@charset may only occur in root document',
|
||||
'',
|
||||
'custom',
|
||||
$oParserState->currentLine()
|
||||
);
|
||||
}
|
||||
if (count($oList->getContents()) > 0) {
|
||||
throw new UnexpectedTokenException(
|
||||
'@charset must be the first parseable token in a document',
|
||||
'',
|
||||
'custom',
|
||||
$oParserState->currentLine()
|
||||
);
|
||||
}
|
||||
$oParserState->setCharset($oAtRule->getCharset()->getString());
|
||||
}
|
||||
return $oAtRule;
|
||||
} elseif ($oParserState->comes('}')) {
|
||||
if (!$oParserState->getSettings()->bLenientParsing) {
|
||||
throw new UnexpectedTokenException('CSS selector', '}', 'identifier', $oParserState->currentLine());
|
||||
} else {
|
||||
if ($bIsRoot) {
|
||||
if ($oParserState->getSettings()->bLenientParsing) {
|
||||
return DeclarationBlock::parse($oParserState);
|
||||
} else {
|
||||
throw new SourceException("Unopened {", $oParserState->currentLine());
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return DeclarationBlock::parse($oParserState, $oList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParserState $oParserState
|
||||
*
|
||||
* @return AtRuleBlockList|KeyFrame|Charset|CSSNamespace|Import|AtRuleSet|null
|
||||
*
|
||||
* @throws SourceException
|
||||
* @throws UnexpectedTokenException
|
||||
* @throws UnexpectedEOFException
|
||||
*/
|
||||
private static function parseAtRule(ParserState $oParserState)
|
||||
{
|
||||
$oParserState->consume('@');
|
||||
$sIdentifier = $oParserState->parseIdentifier();
|
||||
$iIdentifierLineNum = $oParserState->currentLine();
|
||||
$oParserState->consumeWhiteSpace();
|
||||
if ($sIdentifier === 'import') {
|
||||
$oLocation = URL::parse($oParserState);
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$sMediaQuery = null;
|
||||
if (!$oParserState->comes(';')) {
|
||||
$sMediaQuery = trim($oParserState->consumeUntil([';', ParserState::EOF]));
|
||||
}
|
||||
$oParserState->consumeUntil([';', ParserState::EOF], true, true);
|
||||
return new Import($oLocation, $sMediaQuery ?: null, $iIdentifierLineNum);
|
||||
} elseif ($sIdentifier === 'charset') {
|
||||
$sCharset = CSSString::parse($oParserState);
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$oParserState->consumeUntil([';', ParserState::EOF], true, true);
|
||||
return new Charset($sCharset, $iIdentifierLineNum);
|
||||
} elseif (self::identifierIs($sIdentifier, 'keyframes')) {
|
||||
$oResult = new KeyFrame($iIdentifierLineNum);
|
||||
$oResult->setVendorKeyFrame($sIdentifier);
|
||||
$oResult->setAnimationName(trim($oParserState->consumeUntil('{', false, true)));
|
||||
CSSList::parseList($oParserState, $oResult);
|
||||
if ($oParserState->comes('}')) {
|
||||
$oParserState->consume('}');
|
||||
}
|
||||
return $oResult;
|
||||
} elseif ($sIdentifier === 'namespace') {
|
||||
$sPrefix = null;
|
||||
$mUrl = Value::parsePrimitiveValue($oParserState);
|
||||
if (!$oParserState->comes(';')) {
|
||||
$sPrefix = $mUrl;
|
||||
$mUrl = Value::parsePrimitiveValue($oParserState);
|
||||
}
|
||||
$oParserState->consumeUntil([';', ParserState::EOF], true, true);
|
||||
if ($sPrefix !== null && !is_string($sPrefix)) {
|
||||
throw new UnexpectedTokenException('Wrong namespace prefix', $sPrefix, 'custom', $iIdentifierLineNum);
|
||||
}
|
||||
if (!($mUrl instanceof CSSString || $mUrl instanceof URL)) {
|
||||
throw new UnexpectedTokenException(
|
||||
'Wrong namespace url of invalid type',
|
||||
$mUrl,
|
||||
'custom',
|
||||
$iIdentifierLineNum
|
||||
);
|
||||
}
|
||||
return new CSSNamespace($mUrl, $sPrefix, $iIdentifierLineNum);
|
||||
} else {
|
||||
// Unknown other at rule (font-face or such)
|
||||
$sArgs = trim($oParserState->consumeUntil('{', false, true));
|
||||
if (substr_count($sArgs, "(") != substr_count($sArgs, ")")) {
|
||||
if ($oParserState->getSettings()->bLenientParsing) {
|
||||
return null;
|
||||
} else {
|
||||
throw new SourceException("Unmatched brace count in media query", $oParserState->currentLine());
|
||||
}
|
||||
}
|
||||
$bUseRuleSet = true;
|
||||
foreach (explode('/', AtRule::BLOCK_RULES) as $sBlockRuleName) {
|
||||
if (self::identifierIs($sIdentifier, $sBlockRuleName)) {
|
||||
$bUseRuleSet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($bUseRuleSet) {
|
||||
$oAtRule = new AtRuleSet($sIdentifier, $sArgs, $iIdentifierLineNum);
|
||||
RuleSet::parseRuleSet($oParserState, $oAtRule);
|
||||
} else {
|
||||
$oAtRule = new AtRuleBlockList($sIdentifier, $sArgs, $iIdentifierLineNum);
|
||||
CSSList::parseList($oParserState, $oAtRule);
|
||||
if ($oParserState->comes('}')) {
|
||||
$oParserState->consume('}');
|
||||
}
|
||||
}
|
||||
return $oAtRule;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an identifier for a given value. Since identifiers are all keywords, they can be vendor-prefixed.
|
||||
* We need to check for these versions too.
|
||||
*
|
||||
* @param string $sIdentifier
|
||||
* @param string $sMatch
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function identifierIs($sIdentifier, $sMatch)
|
||||
{
|
||||
return (strcasecmp($sIdentifier, $sMatch) === 0)
|
||||
?: preg_match("/^(-\\w+-)?$sMatch$/i", $sIdentifier) === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo()
|
||||
{
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends an item to the list of contents.
|
||||
*
|
||||
* @param RuleSet|CSSList|Import|Charset $oItem
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepend($oItem)
|
||||
{
|
||||
array_unshift($this->aContents, $oItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an item to tje list of contents.
|
||||
*
|
||||
* @param RuleSet|CSSList|Import|Charset $oItem
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function append($oItem)
|
||||
{
|
||||
$this->aContents[] = $oItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splices the list of contents.
|
||||
*
|
||||
* @param int $iOffset
|
||||
* @param int $iLength
|
||||
* @param array<int, RuleSet|CSSList|Import|Charset> $mReplacement
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function splice($iOffset, $iLength = null, $mReplacement = null)
|
||||
{
|
||||
array_splice($this->aContents, $iOffset, $iLength, $mReplacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item from the CSS list.
|
||||
*
|
||||
* @param RuleSet|Import|Charset|CSSList $oItemToRemove
|
||||
* May be a RuleSet (most likely a DeclarationBlock), a Import,
|
||||
* a Charset or another CSSList (most likely a MediaQuery)
|
||||
*
|
||||
* @return bool whether the item was removed
|
||||
*/
|
||||
public function remove($oItemToRemove)
|
||||
{
|
||||
$iKey = array_search($oItemToRemove, $this->aContents, true);
|
||||
if ($iKey !== false) {
|
||||
unset($this->aContents[$iKey]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces an item from the CSS list.
|
||||
*
|
||||
* @param RuleSet|Import|Charset|CSSList $oOldItem
|
||||
* May be a `RuleSet` (most likely a `DeclarationBlock`), an `Import`, a `Charset`
|
||||
* or another `CSSList` (most likely a `MediaQuery`)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function replace($oOldItem, $mNewItem)
|
||||
{
|
||||
$iKey = array_search($oOldItem, $this->aContents, true);
|
||||
if ($iKey !== false) {
|
||||
if (is_array($mNewItem)) {
|
||||
array_splice($this->aContents, $iKey, 1, $mNewItem);
|
||||
} else {
|
||||
array_splice($this->aContents, $iKey, 1, [$mNewItem]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, RuleSet|Import|Charset|CSSList> $aContents
|
||||
*/
|
||||
public function setContents(array $aContents)
|
||||
{
|
||||
$this->aContents = [];
|
||||
foreach ($aContents as $content) {
|
||||
$this->append($content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a declaration block from the CSS list if it matches all given selectors.
|
||||
*
|
||||
* @param DeclarationBlock|array<array-key, Selector>|string $mSelector the selectors to match
|
||||
* @param bool $bRemoveAll whether to stop at the first declaration block found or remove all blocks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeDeclarationBlockBySelector($mSelector, $bRemoveAll = false)
|
||||
{
|
||||
if ($mSelector instanceof DeclarationBlock) {
|
||||
$mSelector = $mSelector->getSelectors();
|
||||
}
|
||||
if (!is_array($mSelector)) {
|
||||
$mSelector = explode(',', $mSelector);
|
||||
}
|
||||
foreach ($mSelector as $iKey => &$mSel) {
|
||||
if (!($mSel instanceof Selector)) {
|
||||
if (!Selector::isValid($mSel)) {
|
||||
throw new UnexpectedTokenException(
|
||||
"Selector did not match '" . Selector::SELECTOR_VALIDATION_RX . "'.",
|
||||
$mSel,
|
||||
"custom"
|
||||
);
|
||||
}
|
||||
$mSel = new Selector($mSel);
|
||||
}
|
||||
}
|
||||
foreach ($this->aContents as $iKey => $mItem) {
|
||||
if (!($mItem instanceof DeclarationBlock)) {
|
||||
continue;
|
||||
}
|
||||
if ($mItem->getSelectors() == $mSelector) {
|
||||
unset($this->aContents[$iKey]);
|
||||
if (!$bRemoveAll) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->render(new OutputFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render(OutputFormat $oOutputFormat)
|
||||
{
|
||||
$sResult = '';
|
||||
$bIsFirst = true;
|
||||
$oNextLevel = $oOutputFormat;
|
||||
if (!$this->isRootList()) {
|
||||
$oNextLevel = $oOutputFormat->nextLevel();
|
||||
}
|
||||
foreach ($this->aContents as $oContent) {
|
||||
$sRendered = $oOutputFormat->safely(function () use ($oNextLevel, $oContent) {
|
||||
return $oContent->render($oNextLevel);
|
||||
});
|
||||
if ($sRendered === null) {
|
||||
continue;
|
||||
}
|
||||
if ($bIsFirst) {
|
||||
$bIsFirst = false;
|
||||
$sResult .= $oNextLevel->spaceBeforeBlocks();
|
||||
} else {
|
||||
$sResult .= $oNextLevel->spaceBetweenBlocks();
|
||||
}
|
||||
$sResult .= $sRendered;
|
||||
}
|
||||
|
||||
if (!$bIsFirst) {
|
||||
// Had some output
|
||||
$sResult .= $oOutputFormat->spaceAfterBlocks();
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the list can not be further outdented. Only important when rendering.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function isRootList();
|
||||
|
||||
/**
|
||||
* @return array<int, RuleSet|Import|Charset|CSSList>
|
||||
*/
|
||||
public function getContents()
|
||||
{
|
||||
return $this->aContents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<array-key, Comment> $aComments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addComments(array $aComments)
|
||||
{
|
||||
$this->aComments = array_merge($this->aComments, $aComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array-key, Comment>
|
||||
*/
|
||||
public function getComments()
|
||||
{
|
||||
return $this->aComments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<array-key, Comment> $aComments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setComments(array $aComments)
|
||||
{
|
||||
$this->aComments = $aComments;
|
||||
}
|
||||
}
|
172
vendor/sabberworm/php-css-parser/src/CSSList/Document.php
vendored
Normal file
172
vendor/sabberworm/php-css-parser/src/CSSList/Document.php
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\OutputFormat;
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\SourceException;
|
||||
use Sabberworm\CSS\Property\Selector;
|
||||
use Sabberworm\CSS\RuleSet\DeclarationBlock;
|
||||
use Sabberworm\CSS\RuleSet\RuleSet;
|
||||
use Sabberworm\CSS\Value\Value;
|
||||
|
||||
/**
|
||||
* The root `CSSList` of a parsed file. Contains all top-level CSS contents, mostly declaration blocks,
|
||||
* but also any at-rules encountered.
|
||||
*/
|
||||
class Document extends CSSBlockList
|
||||
{
|
||||
/**
|
||||
* @param int $iLineNo
|
||||
*/
|
||||
public function __construct($iLineNo = 0)
|
||||
{
|
||||
parent::__construct($iLineNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Document
|
||||
*
|
||||
* @throws SourceException
|
||||
*/
|
||||
public static function parse(ParserState $oParserState)
|
||||
{
|
||||
$oDocument = new Document($oParserState->currentLine());
|
||||
CSSList::parseList($oParserState, $oDocument);
|
||||
return $oDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all `DeclarationBlock` objects recursively.
|
||||
*
|
||||
* @return array<int, DeclarationBlock>
|
||||
*/
|
||||
public function getAllDeclarationBlocks()
|
||||
{
|
||||
/** @var array<int, DeclarationBlock> $aResult */
|
||||
$aResult = [];
|
||||
$this->allDeclarationBlocks($aResult);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all `DeclarationBlock` objects recursively.
|
||||
*
|
||||
* @return array<int, DeclarationBlock>
|
||||
*
|
||||
* @deprecated will be removed in version 9.0; use `getAllDeclarationBlocks()` instead
|
||||
*/
|
||||
public function getAllSelectors()
|
||||
{
|
||||
return $this->getAllDeclarationBlocks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all `RuleSet` objects found recursively in the tree.
|
||||
*
|
||||
* @return array<int, RuleSet>
|
||||
*/
|
||||
public function getAllRuleSets()
|
||||
{
|
||||
/** @var array<int, RuleSet> $aResult */
|
||||
$aResult = [];
|
||||
$this->allRuleSets($aResult);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all `Value` objects found recursively in the tree.
|
||||
*
|
||||
* @param CSSList|RuleSet|string $mElement
|
||||
* the `CSSList` or `RuleSet` to start the search from (defaults to the whole document).
|
||||
* If a string is given, it is used as rule name filter.
|
||||
* @param bool $bSearchInFunctionArguments whether to also return Value objects used as Function arguments.
|
||||
*
|
||||
* @return array<int, Value>
|
||||
*
|
||||
* @see RuleSet->getRules()
|
||||
*/
|
||||
public function getAllValues($mElement = null, $bSearchInFunctionArguments = false)
|
||||
{
|
||||
$sSearchString = null;
|
||||
if ($mElement === null) {
|
||||
$mElement = $this;
|
||||
} elseif (is_string($mElement)) {
|
||||
$sSearchString = $mElement;
|
||||
$mElement = $this;
|
||||
}
|
||||
/** @var array<int, Value> $aResult */
|
||||
$aResult = [];
|
||||
$this->allValues($mElement, $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all `Selector` objects found recursively in the tree.
|
||||
*
|
||||
* Note that this does not yield the full `DeclarationBlock` that the selector belongs to
|
||||
* (and, currently, there is no way to get to that).
|
||||
*
|
||||
* @param string|null $sSpecificitySearch
|
||||
* An optional filter by specificity.
|
||||
* May contain a comparison operator and a number or just a number (defaults to "==").
|
||||
*
|
||||
* @return array<int, Selector>
|
||||
* @example `getSelectorsBySpecificity('>= 100')`
|
||||
*
|
||||
*/
|
||||
public function getSelectorsBySpecificity($sSpecificitySearch = null)
|
||||
{
|
||||
/** @var array<int, Selector> $aResult */
|
||||
$aResult = [];
|
||||
$this->allSelectors($aResult, $sSpecificitySearch);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands all shorthand properties to their long value.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function expandShorthands()
|
||||
{
|
||||
foreach ($this->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->expandShorthands();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create shorthands properties whenever possible.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createShorthands()
|
||||
{
|
||||
foreach ($this->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->createShorthands();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides `render()` to make format argument optional.
|
||||
*
|
||||
* @param OutputFormat|null $oOutputFormat
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render(OutputFormat $oOutputFormat = null)
|
||||
{
|
||||
if ($oOutputFormat === null) {
|
||||
$oOutputFormat = new OutputFormat();
|
||||
}
|
||||
return parent::render($oOutputFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isRootList()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
104
vendor/sabberworm/php-css-parser/src/CSSList/KeyFrame.php
vendored
Normal file
104
vendor/sabberworm/php-css-parser/src/CSSList/KeyFrame.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\OutputFormat;
|
||||
use Sabberworm\CSS\Property\AtRule;
|
||||
|
||||
class KeyFrame extends CSSList implements AtRule
|
||||
{
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $vendorKeyFrame;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $animationName;
|
||||
|
||||
/**
|
||||
* @param int $iLineNo
|
||||
*/
|
||||
public function __construct($iLineNo = 0)
|
||||
{
|
||||
parent::__construct($iLineNo);
|
||||
$this->vendorKeyFrame = null;
|
||||
$this->animationName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $vendorKeyFrame
|
||||
*/
|
||||
public function setVendorKeyFrame($vendorKeyFrame)
|
||||
{
|
||||
$this->vendorKeyFrame = $vendorKeyFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getVendorKeyFrame()
|
||||
{
|
||||
return $this->vendorKeyFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $animationName
|
||||
*/
|
||||
public function setAnimationName($animationName)
|
||||
{
|
||||
$this->animationName = $animationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getAnimationName()
|
||||
{
|
||||
return $this->animationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->render(new OutputFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render(OutputFormat $oOutputFormat)
|
||||
{
|
||||
$sResult = "@{$this->vendorKeyFrame} {$this->animationName}{$oOutputFormat->spaceBeforeOpeningBrace()}{";
|
||||
$sResult .= parent::render($oOutputFormat);
|
||||
$sResult .= '}';
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isRootList()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function atRuleName()
|
||||
{
|
||||
return $this->vendorKeyFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function atRuleArgs()
|
||||
{
|
||||
return $this->animationName;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user