%PDF- %PDF-
Direktori : /home/q/g/b/qgbqkvz/www/wp-content/plugins/wp-scss/scssphp/src/Value/ |
Current File : /home/q/g/b/qgbqkvz/www/wp-content/plugins/wp-scss/scssphp/src/Value/Value.php |
<?php /** * SCSSPHP * * @copyright 2012-2020 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * * @link http://scssphp.github.io/scssphp */ namespace ScssPhp\ScssPhp\Value; use ScssPhp\ScssPhp\Ast\Selector\ComplexSelector; use ScssPhp\ScssPhp\Ast\Selector\CompoundSelector; use ScssPhp\ScssPhp\Ast\Selector\SelectorList; use ScssPhp\ScssPhp\Ast\Selector\SimpleSelector; use ScssPhp\ScssPhp\Exception\SassFormatException; use ScssPhp\ScssPhp\Exception\SassScriptException; use ScssPhp\ScssPhp\Serializer\Serializer; use ScssPhp\ScssPhp\Util\Equatable; use ScssPhp\ScssPhp\Visitor\ValueVisitor; /** * A SassScript value. * * All SassScript values are unmodifiable. New values can be constructed using * subclass constructors like `new SassString`. Untyped values can be cast to * particular types using `assert*()` functions like {@see assertString}, which * throw user-friendly error messages if they fail. */ abstract class Value implements Equatable { /** * Whether the value counts as `true` in an `@if` statement and other contexts * * @return bool */ public function isTruthy(): bool { return true; } /** * The separator for this value as a list. * * All SassScript values can be used as lists. Maps count as lists of pairs, * and all other values count as single-value lists. * * @return string * * @phpstan-return ListSeparator::* */ public function getSeparator(): string { return ListSeparator::UNDECIDED; } /** * Whether this value as a list has brackets. * * All SassScript values can be used as lists. Maps count as lists of pairs, * and all other values count as single-value lists. * * @return bool */ public function hasBrackets(): bool { return false; } /** * This value as a list. * * All SassScript values can be used as lists. Maps count as lists of pairs, * and all other values count as single-value lists. * * @return list<Value> */ public function asList(): array { return [$this]; } /** * The length of {@see asList}. * * This is used to compute {@see sassIndexToListIndex} without allocating a new * list. */ protected function getLengthAsList(): int { return 1; } /** * Calls the appropriate visit method on $visitor. * * @template T * * @param ValueVisitor<T> $visitor * * @return T * * @internal */ abstract public function accept(ValueVisitor $visitor); /** * Converts $sassIndex into a PHP-style index into the list returned by * {@see asList}. * * Sass indexes are one-based, while PHP indexes are zero-based. Sass * indexes may also be negative in order to index from the end of the list. * * @throws SassScriptException if $sassIndex isn't a number, if that * number isn't an integer, or if that integer isn't a valid index for * {@see asList}. If $sassIndex came from a function argument, $name is the * argument name (without the `$`). It's used for error reporting. */ public function sassIndexToListIndex(Value $sassIndex, ?string $name = null): int { $index = $sassIndex->assertNumber($name)->assertInt($name); if ($index === 0) { throw SassScriptException::forArgument('List index may not be 0.', $name); } $lengthAsList = $this->getLengthAsList(); if (abs($index) > $lengthAsList) { throw SassScriptException::forArgument("Invalid index $sassIndex for a list with $lengthAsList elements.", $name); } return $index < 0 ? $lengthAsList + $index : $index - 1; } /** * Throws a {@see SassScriptException} if $this isn't a boolean. * * Note that generally, functions should use {@see isTruthy} rather than requiring * a literal boolean. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @param string|null $name * * @return SassBoolean * * @throws SassScriptException */ public function assertBoolean(?string $name = null): SassBoolean { throw SassScriptException::forArgument("$this is not a boolean.", $name); } /** * Throws a {@see SassScriptException} if $this isn't a calculation. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @param string|null $name * * @return SassCalculation * * @throws SassScriptException */ public function assertCalculation(?string $name = null): SassCalculation { throw SassScriptException::forArgument("$this is not a calculation.", $name); } /** * Throws a {@see SassScriptException} if $this isn't a color. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @param string|null $name * * @return SassColor * * @throws SassScriptException */ public function assertColor(?string $name = null): SassColor { throw SassScriptException::forArgument("$this is not a color.", $name); } /** * Throws a {@see SassScriptException} if $this isn't a string. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @param string|null $name * * @return SassFunction * * @throws SassScriptException */ public function assertFunction(?string $name = null): SassFunction { throw SassScriptException::forArgument("$this is not a function.", $name); } /** * Throws a {@see SassScriptException} if $this isn't a map. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @param string|null $name * * @return SassMap * * @throws SassScriptException */ public function assertMap(?string $name = null): SassMap { throw SassScriptException::forArgument("$this is not a map.", $name); } /** * Return $this as a SassMap if it is one (including empty lists) or null otherwise. * * @return SassMap|null */ public function tryMap(): ?SassMap { return null; } /** * Throws a {@see SassScriptException} if $this isn't a number. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @param string|null $name * * @return SassNumber * * @throws SassScriptException */ public function assertNumber(?string $name = null): SassNumber { throw SassScriptException::forArgument("$this is not a number.", $name); } /** * Throws a {@see SassScriptException} if $this isn't a string. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @param string|null $name * * @return SassString * * @throws SassScriptException */ public function assertString(?string $name = null): SassString { throw SassScriptException::forArgument("$this is not a string.", $name); } /** * Parses $this as a selector list, in the same manner as the * `selector-parse()` function. * * @throws SassScriptException if this isn't a type that can be parsed as a * selector, or if parsing fails. If $allowParent is `true`, this allows * {@see ParentSelector}s. Otherwise, they're considered parse errors. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @internal */ public function assertSelector(?string $name = null, bool $allowParent = false): SelectorList { $string = $this->selectorString($name); try { return SelectorList::parse($string, null, null, $allowParent); } catch (SassFormatException $e) { throw SassScriptException::forArgument($e->getMessage(), $name, $e); } } /** * Parses $this as a simple selector, in the same manner as the * `selector-parse()` function. * * @throws SassScriptException if this isn't a type that can be parsed as a * selector, or if parsing fails. If $allowParent is `true`, this allows * {@see ParentSelector}s. Otherwise, they're considered parse errors. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @internal */ public function assertSimpleSelector(?string $name = null, bool $allowParent = false): SimpleSelector { $string = $this->selectorString($name); try { return SimpleSelector::parse($string, null, null, $allowParent); } catch (SassFormatException $e) { throw SassScriptException::forArgument($e->getMessage(), $name, $e); } } /** * Parses $this as a compound selector, in the same manner as the * `selector-parse()` function. * * @throws SassScriptException if this isn't a type that can be parsed as a * selector, or if parsing fails. If $allowParent is `true`, this allows * {@see ParentSelector}s. Otherwise, they're considered parse errors. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @internal */ public function assertCompoundSelector(?string $name = null, bool $allowParent = false): CompoundSelector { $string = $this->selectorString($name); try { return CompoundSelector::parse($string, null, null, $allowParent); } catch (SassFormatException $e) { throw SassScriptException::forArgument($e->getMessage(), $name, $e); } } /** * Parses $this as a complex selector, in the same manner as the * `selector-parse()` function. * * @throws SassScriptException if this isn't a type that can be parsed as a * selector, or if parsing fails. If $allowParent is `true`, this allows * {@see ParentSelector}s. Otherwise, they're considered parse errors. * * If this came from a function argument, $name is the argument name * (without the `$`). It's used for error reporting. * * @internal */ public function assertComplexSelector(?string $name = null, bool $allowParent = false): ComplexSelector { $string = $this->selectorString($name); try { return ComplexSelector::parse($string, null, null, $allowParent); } catch (SassFormatException $e) { throw SassScriptException::forArgument($e->getMessage(), $name, $e); } } /** * Converts a `selector-parse()`-style input into a string that can be * parsed. * * @throws SassScriptException if $this isn't a type or a structure that * can be parsed as a selector. */ private function selectorString(?string $name): string { $string = $this->selectorStringOrNull(); if ($string !== null) { return $string; } throw SassScriptException::forArgument("$this is not a valid selector: it must be a string,\na list of strings, or a list of lists of strings.", $name); } /** * Converts a `selector-parse()`-style input into a string that can be * parsed. * * Returns `null` if $this isn't a type or a structure that can be parsed as * a selector. */ private function selectorStringOrNull(): ?string { if ($this instanceof SassString) { return $this->getText(); } if (!$this instanceof SassList) { return null; } $list = $this; if (\count($list->asList()) === 0) { return null; } $result = []; switch ($list->getSeparator()) { case ListSeparator::COMMA: foreach ($list->asList() as $complex) { if ($complex instanceof SassString) { $result[] = $complex->getText(); } elseif ($complex instanceof SassList && $complex->getSeparator() === ListSeparator::SPACE) { $string = $complex->selectorStringOrNull(); if ($string === null) { return null; } $result[] = $string; } else { return null; } } break; case ListSeparator::SLASH: return null; default: foreach ($list->asList() as $compound) { if ($compound instanceof SassString) { $result[] = $compound->getText(); } else { return null; } } break; } return implode($list->getSeparator() === ListSeparator::COMMA ? ', ' : ' ', $result); } /** * Whether the value will be represented in CSS as the empty string. * * @return bool * * @internal */ public function isBlank(): bool { return false; } /** * Whether this is a value that CSS may treat as a number, such as `calc()` or `var()`. * * Functions that shadow plain CSS functions need to gracefully handle when * these arguments are passed in. * * @return bool * * @internal */ public function isSpecialNumber(): bool { return false; } /** * Whether this is a call to `var()`, which may be substituted in CSS for a custom property value. * * Functions that shadow plain CSS functions need to gracefully handle when * these arguments are passed in. * * @return bool * * @internal */ public function isVar(): bool { return false; } /** * Returns a new list containing $contents that defaults to this value's * separator and brackets. * * @param list<Value> $contents * @param string|null $separator * @param bool|null $brackets * * @return SassList * * @phpstan-param ListSeparator::*|null $separator */ public function withListContents(array $contents, ?string $separator = null, ?bool $brackets = null): SassList { return new SassList($contents, $separator ?? $this->getSeparator(), $brackets ?? $this->hasBrackets()); } /** * The SassScript = operation * * @param Value $other * * @return Value * * @internal */ public function singleEquals(Value $other): Value { return new SassString(sprintf('%s=%s', $this->toCssString(), $other->toCssString()), false); } /** * The SassScript `>` operation. * * @param Value $other * * @return SassBoolean * * @internal */ public function greaterThan(Value $other): SassBoolean { throw new SassScriptException("Undefined operation \"$this > $other\"."); } /** * The SassScript `>=` operation. * * @param Value $other * * @return SassBoolean * * @internal */ public function greaterThanOrEquals(Value $other): SassBoolean { throw new SassScriptException("Undefined operation \"$this >= $other\"."); } /** * The SassScript `<` operation. * * @param Value $other * * @return SassBoolean * * @internal */ public function lessThan(Value $other): SassBoolean { throw new SassScriptException("Undefined operation \"$this < $other\"."); } /** * The SassScript `<=` operation. * * @param Value $other * * @return SassBoolean * * @internal */ public function lessThanOrEquals(Value $other): SassBoolean { throw new SassScriptException("Undefined operation \"$this <= $other\"."); } /** * The SassScript `*` operation. * * @param Value $other * * @return Value * * @internal */ public function times(Value $other): Value { throw new SassScriptException("Undefined operation \"$this * $other\"."); } /** * The SassScript `%` operation. * * @param Value $other * * @return Value * * @internal */ public function modulo(Value $other): Value { throw new SassScriptException("Undefined operation \"$this % $other\"."); } /** * The SassScript `+` operation. * * @param Value $other * * @return Value * * @internal */ public function plus(Value $other): Value { if ($other instanceof SassString) { return new SassString($this->toCssString() . $other->getText(), $other->hasQuotes()); } if ($other instanceof SassCalculation) { throw new SassScriptException("Undefined operation \"$this + $other\"."); } return new SassString($this->toCssString() . $other->toCssString(), false); } /** * The SassScript `-` operation. * * @param Value $other * * @return Value * * @internal */ public function minus(Value $other): Value { if ($other instanceof SassCalculation) { throw new SassScriptException("Undefined operation \"$this - $other\"."); } return new SassString(sprintf('%s-%s', $this->toCssString(), $other->toCssString()), false); } /** * The SassScript `/` operation. * * @param Value $other * * @return Value * * @internal */ public function dividedBy(Value $other): Value { return new SassString(sprintf('%s/%s', $this->toCssString(), $other->toCssString()), false); } /** * The SassScript unary `+` operation. * * @return Value * * @internal */ public function unaryPlus(): Value { return new SassString(sprintf('+%s', $this->toCssString()), false); } /** * The SassScript unary `-` operation. * * @return Value * * @internal */ public function unaryMinus(): Value { return new SassString(sprintf('-%s', $this->toCssString()), false); } /** * The SassScript unary `/` operation. * * @return Value * * @internal */ public function unaryDivide(): Value { return new SassString(sprintf('/%s', $this->toCssString()), false); } /** * The SassScript unary `not` operation. * * @return Value * * @internal */ public function unaryNot(): Value { return SassBoolean::create(false); } /** * Returns a copy of $this without {@see SassNumber::$asSlash} set. * * If this isn't a SassNumber, return it as-is. * * @return Value * * @internal */ public function withoutSlash(): Value { return $this; } /** * Returns a valid CSS representation of $this. * * Use {@see toString} instead to get a string representation even if this * isn't valid CSS. * * Internal-only: If $quote is `false`, quoted strings are emitted without * quotes. * * @throws SassScriptException if $this cannot be represented in plain CSS. */ final public function toCssString(bool $quote = true): string { return Serializer::serializeValue($this, false, $quote); } /** * Returns a Sass representation of $this. * * Note that this is equivalent to calling `inspect()` on the value, and thus * won't reflect the user's output settings. {@see toCssString} should be used * instead to convert $this to CSS. * * @return string */ final public function __toString(): string { return Serializer::serializeValue($this, true); } }