File manager - Edit - /home/ferretapmx/public_html/plugins/system/helixultimate/vendor/scssphp/scssphp/src/Ast/Selector/SelectorList.php
Back
<?php /** * SCSSPHP * * @copyright 2012-2020 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * * @link http://scssphp.github.io/scssphp */ namespace ScssPhp\ScssPhp\Ast\Selector; use League\Uri\Contracts\UriInterface; use ScssPhp\ScssPhp\Ast\Css\CssValue; use ScssPhp\ScssPhp\Exception\MultiSpanSassException; use ScssPhp\ScssPhp\Exception\SassFormatException; use ScssPhp\ScssPhp\Exception\SassScriptException; use ScssPhp\ScssPhp\Exception\SimpleSassException; use ScssPhp\ScssPhp\Extend\ExtendUtil; use ScssPhp\ScssPhp\Logger\LoggerInterface; use ScssPhp\ScssPhp\Parser\InterpolationMap; use ScssPhp\ScssPhp\Parser\SelectorParser; use ScssPhp\ScssPhp\Util\EquatableUtil; use ScssPhp\ScssPhp\Util\ListUtil; use ScssPhp\ScssPhp\Util\SpanUtil; use ScssPhp\ScssPhp\Value\ListSeparator; use ScssPhp\ScssPhp\Value\SassList; use ScssPhp\ScssPhp\Value\SassString; use ScssPhp\ScssPhp\Visitor\SelectorVisitor; use SourceSpan\FileSpan; /** * A selector list. * * A selector list is composed of {@see ComplexSelector}s. It matches any element * that matches any of the component selectors. * * @internal */ final class SelectorList extends Selector { /** * The components of this selector. * * This is never empty. * * @var non-empty-list<ComplexSelector> */ private readonly array $components; /** * Parses a selector list from $contents. * * If passed, $url is the name of the file from which $contents comes. If * $allowParent is false, this doesn't allow {@see ParentSelector}s. If * $plainCss is true, this parses the selector as plain CSS rather than * unresolved Sass. * * If passed, $interpolationMap maps the text of $contents back to the * original location of the selector in the source file. * * @throws SassFormatException if parsing fails. */ public static function parse(string $contents, ?LoggerInterface $logger = null, ?InterpolationMap $interpolationMap = null, ?UriInterface $url = null, bool $allowParent = true, bool $plainCss = false): SelectorList { return (new SelectorParser($contents, $logger, $url, $allowParent, $interpolationMap, $plainCss))->parse(); } /** * @param list<ComplexSelector> $components */ public function __construct(array $components, FileSpan $span) { if ($components === []) { throw new \InvalidArgumentException('components may not be empty.'); } $this->components = $components; parent::__construct($span); } /** * @return non-empty-list<ComplexSelector> */ public function getComponents(): array { return $this->components; } /** * Returns a SassScript list that represents this selector. * * This has the same format as a list returned by `selector-parse()`. */ public function asSassList(): SassList { return new SassList(array_map(static function (ComplexSelector $complex) { $result = []; foreach ($complex->getLeadingCombinators() as $combinator) { $result[] = new SassString($combinator, false); } foreach ($complex->getComponents() as $component) { $result[] = new SassString((string) $component->getSelector(), false); foreach ($component->getCombinators() as $combinator) { $result[] = new SassString($combinator, false); } } return new SassList($result, ListSeparator::SPACE); }, $this->components), ListSeparator::COMMA); } public function accept(SelectorVisitor $visitor) { return $visitor->visitSelectorList($this); } /** * Returns a {@see SelectorList} that matches only elements that are matched by * both this and $other. * * If no such list can be produced, returns `null`. */ public function unify(SelectorList $other): ?SelectorList { $contents = []; foreach ($this->components as $complex1) { foreach ($other->components as $complex2) { $unified = ExtendUtil::unifyComplex([$complex1, $complex2], $complex1->getSpan()); if ($unified === null) { continue; } foreach ($unified as $complex) { $contents[] = $complex; } } } return \count($contents) === 0 ? null : new SelectorList($contents, $this->getSpan()); } /** * Returns a new selector list that represents $this nested within $parent. * * By default, this replaces {@see ParentSelector}s in $this with $parent. If * $preserveParentSelectors is true, this instead preserves those selectors * as parent selectors. * * If $implicitParent is true, this prepends $parent to any * {@see ComplexSelector}s in this that don't contain explicit {@see ParentSelector}s, * or to _all_ {@see ComplexSelector}s if $preserveParentSelectors is true. * * The given $parent may be `null`, indicating that this has no parents. If * so, this list is returned as-is if it doesn't contain any explicit * {@see ParentSelector}s or if $preserveParentSelectors is true. Otherwise, this * throws a {@see SassScriptException}. */ public function nestWithin(?SelectorList $parent, bool $implicitParent = true, bool $preserveParentSelectors = false): SelectorList { if ($parent === null) { if ($preserveParentSelectors) { return $this; } $parentSelector = $this->accept(new ParentSelectorVisitor()); if ($parentSelector === null) { return $this; } throw new SimpleSassException('Top-level selectors may not contain the parent selector "&".', $parentSelector->getSpan()); } return new SelectorList(ListUtil::flattenVertically(array_map(function (ComplexSelector $complex) use ($parent, $implicitParent, $preserveParentSelectors) { if ($preserveParentSelectors || !self::containsParentSelector($complex)) { if (!$implicitParent) { return [$complex]; } return array_map(fn(ComplexSelector $parentComplex) => $parentComplex->concatenate($complex, $complex->getSpan()), $parent->getComponents()); } /** @var list<ComplexSelector> $newComplexes */ $newComplexes = []; foreach ($complex->getComponents() as $component) { $resolved = self::nestWithinCompound($component, $parent); if ($resolved === null) { if (\count($newComplexes) === 0) { $newComplexes[] = new ComplexSelector($complex->getLeadingCombinators(), [$component], $complex->getSpan(), false); } else { $newComplexes = array_map(fn ($newComplex) => $newComplex->withAdditionalComponent($component, $complex->getSpan()), $newComplexes); } } elseif (\count($newComplexes) === 0) { if (\count($complex->getLeadingCombinators()) === 0) { $newComplexes = $resolved; } else { $newComplexes = array_map(fn (ComplexSelector $resolvedComplex) => new ComplexSelector( array_merge($complex->getLeadingCombinators(), $resolvedComplex->getLeadingCombinators()), $resolvedComplex->getComponents(), $complex->getSpan(), $resolvedComplex->getLineBreak() ), $resolved); } } else { $previousComplexes = $newComplexes; $newComplexes = []; foreach ($previousComplexes as $newComplex) { foreach ($resolved as $resolvedComplex) { $newComplexes[] = $newComplex->concatenate($resolvedComplex, $newComplex->getSpan()); } } } } return $newComplexes; }, $this->components)), $this->getSpan()); } /** * Whether this is a superselector of $other. * * That is, whether this matches every element that $other matches, as well * as possibly additional elements. */ public function isSuperselector(SelectorList $other): bool { return ExtendUtil::listIsSuperselector($this->components, $other->components); } public function equals(object $other): bool { return $other instanceof SelectorList && EquatableUtil::listEquals($this->components, $other->components); } /** * Returns a new selector list based on $component with all * {@see ParentSelector}s replaced with $parent. * * Returns `null` if $component doesn't contain any {@see ParentSelector}s. * * @return list<ComplexSelector>|null */ private static function nestWithinCompound(ComplexSelectorComponent $component, SelectorList $parent): ?array { $simples = $component->getSelector()->getComponents(); $containsSelectorPseudo = false; foreach ($simples as $simple) { if (!$simple instanceof PseudoSelector) { continue; } $selector = $simple->getSelector(); if ($selector !== null && self::containsParentSelector($selector)) { $containsSelectorPseudo = true; break; } } if (!$containsSelectorPseudo && !$simples[0] instanceof ParentSelector) { return null; } if ($containsSelectorPseudo) { $resolvedSimples = array_map(function (SimpleSelector $simple) use ($parent): SimpleSelector { if (!$simple instanceof PseudoSelector) { return $simple; } $selector = $simple->getSelector(); if ($selector === null) { return $simple; } if (!self::containsParentSelector($selector)) { return $simple; } return $simple->withSelector($selector->nestWithin($parent, false)); }, $simples); } else { $resolvedSimples = $simples; } $parentSelector = $simples[0]; if (!$parentSelector instanceof ParentSelector) { return [ new ComplexSelector([], [ new ComplexSelectorComponent( new CompoundSelector($resolvedSimples, $component->getSelector()->getSpan()), $component->getCombinators(), $component->getSpan() ), ], $component->getSpan()), ]; } if (\count($simples) === 1 && $parentSelector->getSuffix() === null) { return $parent->withAdditionalCombinators($component->getCombinators())->getComponents(); } return array_map(function (ComplexSelector $complex) use ($parentSelector, $resolvedSimples, $component) { $lastComponent = $complex->getLastComponent(); if (\count($lastComponent->getCombinators()) !== 0) { throw new MultiSpanSassException("Selector \"$complex\" can't be used as a parent in a compound selector.", SpanUtil::trimRight($lastComponent->getSpan()), 'outer selector', ['parent selector' => $parentSelector->getSpan()]); } $suffix = $parentSelector->getSuffix(); $lastSimples = $lastComponent->getSelector()->getComponents(); if ($suffix !== null) { $last = new CompoundSelector(array_merge( ListUtil::exceptLast($lastSimples), [ListUtil::last($lastSimples)->addSuffix($suffix)], array_slice($resolvedSimples, 1) ), $component->getSelector()->getSpan()); } else { $last = new CompoundSelector(array_merge($lastSimples, array_slice($resolvedSimples, 1)), $component->getSelector()->getSpan()); } $components = ListUtil::exceptLast($complex->getComponents()); $components[] = new ComplexSelectorComponent($last, $component->getCombinators(), $component->getSpan()); return new ComplexSelector($complex->getLeadingCombinators(), $components, $component->getSpan(), $complex->getLineBreak()); }, $parent->getComponents()); } /** * Returns a copy of `this` with $combinators added to the end of each * complex selector in {@see components}]. * * @param list<CssValue<Combinator>> $combinators */ public function withAdditionalCombinators(array $combinators): SelectorList { if ($combinators === []) { return $this; } return new SelectorList(array_map(fn(ComplexSelector $complex) => $complex->withAdditionalCombinators($combinators), $this->components), $this->getSpan()); } /** * Returns whether $selector recursively contains a parent selector. */ private static function containsParentSelector(Selector $selector): bool { return $selector->accept(new ParentSelectorVisitor()) !== null; } }
| ver. 1.4 |
Github
|
.
| PHP 8.2.32 | Generation time: 0.06 |
proxy
|
phpinfo
|
Settings