Файловый менеджер - Редактировать - /var/www/vhosts/aviointeriors.dev1.mndrn.cloud/routes/update/nunomaduro.zip
Назад
PK 6n]w�6� � termwind/docker/Dockerfilenu �[��� FROM php:8.2-cli-alpine # INSTALL AND UPDATE COMPOSER COPY --from=composer /usr/bin/composer /usr/bin/composer RUN composer self-update WORKDIR /usr/src/app COPY . . # INSTALL YOUR DEPENDENCIES RUN composer install --prefer-dist PK 6n]E_> I I termwind/LICENSE.mdnu ȯ�� The MIT License (MIT) Copyright (c) Nuno Maduro <enunomaduro@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK 6n]m���� � termwind/Makefilenu �[��� # Well documented Makefiles DEFAULT_GOAL := help help: @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-40s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) ##@ [Docker] start: ## Spin up the container docker-compose up -d stop: ## Shut down the containers docker-compose down build: ## Build all docker images docker-compose build ##@ [Application] composer: ## Run composer commands. Specify the command e.g. via "make composer ARGS="install|update|require <dependency>" docker-compose run --rm app composer $(ARGS) lint: ## Run the Linter docker-compose run --rm app ./vendor/bin/pint -v test-lint: ## Run the Linter Test docker-compose run --rm app ./vendor/bin/pint --test -v test-types: ## Run the PHPStan analysis docker-compose run --rm app ./vendor/bin/phpstan analyse --ansi test-unit: ## Run the Pest Test Suite docker-compose run --rm app ./vendor/bin/pest --colors=always test: ## Run the tests. Apply arguments via make test ARGS="--init" make test-lint && make test-types && make test-unit PK 6n]��� termwind/composer.jsonnu �[��� { "name": "nunomaduro/termwind", "description": "Its like Tailwind CSS, but for the console.", "keywords": ["php", "cli", "package", "console", "css", "style"], "license": "MIT", "authors": [ { "name": "Nuno Maduro", "email": "enunomaduro@gmail.com" } ], "require": { "php": "^8.0", "ext-mbstring": "*", "symfony/console": "^5.3.0|^6.0.0" }, "require-dev": { "ergebnis/phpstan-rules": "^1.0.", "illuminate/console": "^8.0|^9.0", "illuminate/support": "^8.0|^9.0", "laravel/pint": "^1.0.0", "pestphp/pest": "^1.21.0", "pestphp/pest-plugin-mock": "^1.0", "phpstan/phpstan": "^1.4.6", "phpstan/phpstan-strict-rules": "^1.1.0", "symfony/var-dumper": "^5.2.7|^6.0.0", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "autoload": { "psr-4": { "Termwind\\": "src/" }, "files": [ "src/Functions.php" ] }, "autoload-dev": { "psr-4": { "Tests\\": "tests/" } }, "minimum-stability": "dev", "prefer-stable": true, "config": { "sort-packages": true, "preferred-install": "dist", "allow-plugins": { "pestphp/pest-plugin": true } }, "scripts": { "lint": "pint -v", "test:lint": "pint --test -v", "test:types": "phpstan analyse --ansi", "test:unit": "pest --colors=always", "test": [ "@test:lint", "@test:types", "@test:unit" ] }, "extra": { "laravel": { "providers": [ "Termwind\\Laravel\\TermwindServiceProvider" ] } } } PK 6n]�2B� � termwind/docker-compose.ymlnu �[��� version: '3' services: app: image: termwind-docker container_name: termwind-docker stdin_open: true tty: true build: context: . dockerfile: docker/Dockerfile volumes: - .:/usr/src/app PK 6n]��,L, , # termwind/src/ValueObjects/Style.phpnu �[��� <?php declare(strict_types=1); namespace Termwind\ValueObjects; use Closure; use Termwind\Actions\StyleToMethod; use Termwind\Exceptions\InvalidColor; /** * @internal */ final class Style { /** * Creates a new value object instance. * * @param Closure(Styles $styles, string|int ...$argument): Styles $callback */ public function __construct(private Closure $callback, private string $color = '') { // .. } /** * Apply the given set of styles to the styles. */ public function apply(string $styles): void { $callback = clone $this->callback; $this->callback = static function ( Styles $formatter, string|int ...$arguments ) use ($callback, $styles): Styles { $formatter = $callback($formatter, ...$arguments); return StyleToMethod::multiple($formatter, $styles); }; } /** * Sets the color to the style. */ public function color(string $color): void { if (preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $color) < 1) { throw new InvalidColor(sprintf('The color %s is invalid.', $color)); } $this->color = $color; } /** * Gets the color. */ public function getColor(): string { return $this->color; } /** * Styles the given formatter with this style. */ public function __invoke(Styles $styles, string|int ...$arguments): Styles { return ($this->callback)($styles, ...$arguments); } } PK 6n]�,��m �m $ termwind/src/ValueObjects/Styles.phpnu �[��� <?php declare(strict_types=1); namespace Termwind\ValueObjects; use Closure; use Termwind\Actions\StyleToMethod; use Termwind\Components\Element; use Termwind\Components\Hr; use Termwind\Components\Li; use Termwind\Components\Ol; use Termwind\Components\Ul; use Termwind\Enums\Color; use Termwind\Exceptions\ColorNotFound; use Termwind\Exceptions\InvalidStyle; use Termwind\Repositories\Styles as StyleRepository; use function Termwind\terminal; /** * @internal */ final class Styles { /** * Finds all the styling on a string. */ public const STYLING_REGEX = "/\<[\w=#\/\;,:.&,%?-]+\>|\\e\[\d+m/"; /** @var array<int, string> */ private array $styles = []; private ?Element $element = null; /** * Creates a Style formatter instance. * * @param array<string, mixed> $properties * @param array<string, Closure(string, array<string, string|int>, array<string, int[]>): string> $textModifiers * @param array<string, Closure(string, array<string, string|int>): string> $styleModifiers * @param string[] $defaultStyles */ final public function __construct( private array $properties = [ 'colors' => [], 'options' => [], 'isFirstChild' => false, ], private array $textModifiers = [], private array $styleModifiers = [], private array $defaultStyles = [] ) { } /** * @param Element $element * @return $this */ public function setElement(Element $element): self { $this->element = $element; return $this; } /** * Gets default styles. * * @return string[] */ public function defaultStyles(): array { return $this->defaultStyles; } /** * Gets the element's style properties. * * @return array<string, mixed> */ final public function getProperties(): array { return $this->properties; } /** * Sets the element's style properties. * * @param array<string, mixed> $properties */ public function setProperties(array $properties): self { $this->properties = $properties; return $this; } /** * Sets the styles to the element. */ final public function setStyle(string $style): self { $this->styles = array_unique(array_merge($this->styles, [$style])); return $this; } /** * Checks if the element has the style. */ final public function hasStyle(string $style): bool { return in_array($style, $this->styles, true); } /** * Adds a style to the element. */ final public function addStyle(string $style): self { return StyleToMethod::multiple($this, $style); } /** * Inherit styles from given Styles object. */ final public function inheritFromStyles(self $styles): self { foreach (['ml', 'mr', 'pl', 'pr', 'width', 'minWidth', 'maxWidth', 'spaceY', 'spaceX'] as $style) { $this->properties['parentStyles'][$style] = array_merge( $this->properties['parentStyles'][$style] ?? [], $styles->properties['parentStyles'][$style] ?? [] ); $this->properties['parentStyles'][$style][] = $styles->properties['styles'][$style] ?? 0; } $this->properties['parentStyles']['justifyContent'] = $styles->properties['styles']['justifyContent'] ?? false; foreach (['bg', 'fg'] as $colorType) { $value = (array) ($this->properties['colors'][$colorType] ?? []); $parentValue = (array) ($styles->properties['colors'][$colorType] ?? []); if ($value === [] && $parentValue !== []) { $this->properties['colors'][$colorType] = $styles->properties['colors'][$colorType]; } } if (! is_null($this->properties['options']['bold'] ?? null) || ! is_null($styles->properties['options']['bold'] ?? null)) { $this->properties['options']['bold'] = $this->properties['options']['bold'] ?? $styles->properties['options']['bold'] ?? false; } return $this; } /** * Adds a background color to the element. */ final public function bg(string $color, int $variant = 0): self { return $this->with(['colors' => [ 'bg' => $this->getColorVariant($color, $variant), ]]); } /** * Adds a bold style to the element. */ final public function fontBold(): self { return $this->with(['options' => [ 'bold' => true, ]]); } /** * Removes the bold style on the element. */ final public function fontNormal(): self { return $this->with(['options' => [ 'bold' => false, ]]); } /** * Adds a bold style to the element. */ final public function strong(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[1m%s\e[0m", $text); return $this; } /** * Adds an italic style to the element. */ final public function italic(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[3m%s\e[0m", $text); return $this; } /** * Adds an underline style. */ final public function underline(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[4m%s\e[0m", $text); return $this; } /** * Adds the given margin left to the element. */ final public function ml(int $margin): self { return $this->with(['styles' => [ 'ml' => $margin, ]]); } /** * Adds the given margin right to the element. */ final public function mr(int $margin): self { return $this->with(['styles' => [ 'mr' => $margin, ]]); } /** * Adds the given margin bottom to the element. */ final public function mb(int $margin): self { return $this->with(['styles' => [ 'mb' => $margin, ]]); } /** * Adds the given margin top to the element. */ final public function mt(int $margin): self { return $this->with(['styles' => [ 'mt' => $margin, ]]); } /** * Adds the given horizontal margin to the element. */ final public function mx(int $margin): self { return $this->with(['styles' => [ 'ml' => $margin, 'mr' => $margin, ]]); } /** * Adds the given vertical margin to the element. */ final public function my(int $margin): self { return $this->with(['styles' => [ 'mt' => $margin, 'mb' => $margin, ]]); } /** * Adds the given margin to the element. */ final public function m(int $margin): self { return $this->my($margin)->mx($margin); } /** * Adds the given padding left to the element. */ final public function pl(int $padding): static { return $this->with(['styles' => [ 'pl' => $padding, ]]); } /** * Adds the given padding right. */ final public function pr(int $padding): static { return $this->with(['styles' => [ 'pr' => $padding, ]]); } /** * Adds the given horizontal padding. */ final public function px(int $padding): self { return $this->pl($padding)->pr($padding); } /** * Adds the given padding top. */ final public function pt(int $padding): static { return $this->with(['styles' => [ 'pt' => $padding, ]]); } /** * Adds the given padding bottom. */ final public function pb(int $padding): static { return $this->with(['styles' => [ 'pb' => $padding, ]]); } /** * Adds the given vertical padding. */ final public function py(int $padding): self { return $this->pt($padding)->pb($padding); } /** * Adds the given padding. */ final public function p(int $padding): self { return $this->pt($padding)->pr($padding)->pb($padding)->pl($padding); } /** * Adds the given vertical margin to the childs, ignoring the first child. */ final public function spaceY(int $space): self { return $this->with(['styles' => [ 'spaceY' => $space, ]]); } /** * Adds the given horizontal margin to the childs, ignoring the first child. */ final public function spaceX(int $space): self { return $this->with(['styles' => [ 'spaceX' => $space, ]]); } /** * Adds a border on top of each element. */ final public function borderT(int $width = 1): self { if (! $this->element instanceof Hr) { throw new InvalidStyle('`border-t` can only be used on an "hr" element.'); } $this->styleModifiers[__METHOD__] = function ($text, $styles): string { $length = $this->getLength($text); if ($length < 1) { $margins = (int) ($styles['ml'] ?? 0) + ($styles['mr'] ?? 0); return str_repeat('─', self::getParentWidth($this->properties['parentStyles'] ?? []) - $margins); } return str_repeat('─', $length); }; return $this; } /** * Adds a text alignment or color to the element. */ final public function text(string $value, int $variant = 0): self { if (in_array($value, ['left', 'right', 'center'], true)) { return $this->with(['styles' => [ 'text-align' => $value, ]]); } return $this->with(['colors' => [ 'fg' => $this->getColorVariant($value, $variant), ]]); } /** * Truncates the text of the element. */ final public function truncate(int $limit = 0, string $end = '…'): self { $this->textModifiers[__METHOD__] = function ($text, $styles) use ($limit, $end): string { $width = $styles['width'] ?? 0; if (is_string($width)) { $width = self::calcWidthFromFraction( $width, $styles, $this->properties['parentStyles'] ?? [] ); } [, $paddingRight, , $paddingLeft] = $this->getPaddings(); $width -= $paddingRight + $paddingLeft; $limit = $limit > 0 ? $limit : $width; if ($limit === 0) { return $text; } $limit -= mb_strwidth($end, 'UTF-8'); if ($this->getLength($text) <= $limit) { return $text; } return rtrim(self::trimText($text, $limit).$end); }; return $this; } /** * Forces the width of the element. */ final public function w(int|string $width): static { return $this->with(['styles' => [ 'width' => $width, ]]); } /** * Forces the element width to the full width of the terminal. */ final public function wFull(): static { return $this->w('1/1'); } /** * Removes the width set on the element. */ final public function wAuto(): static { return $this->with(['styles' => [ 'width' => null, ]]); } /** * Defines a minimum width of an element. */ final public function minW(int|string $width): static { return $this->with(['styles' => [ 'minWidth' => $width, ]]); } /** * Defines a maximum width of an element. */ final public function maxW(int|string $width): static { return $this->with(['styles' => [ 'maxWidth' => $width, ]]); } /** * Makes the element's content uppercase. */ final public function uppercase(): self { $this->textModifiers[__METHOD__] = static fn ($text): string => mb_strtoupper($text, 'UTF-8'); return $this; } /** * Makes the element's content lowercase. */ final public function lowercase(): self { $this->textModifiers[__METHOD__] = static fn ($text): string => mb_strtolower($text, 'UTF-8'); return $this; } /** * Makes the element's content capitalize. */ final public function capitalize(): self { $this->textModifiers[__METHOD__] = static fn ($text): string => mb_convert_case($text, MB_CASE_TITLE, 'UTF-8'); return $this; } /** * Makes the element's content in snakecase. */ final public function snakecase(): self { $this->textModifiers[__METHOD__] = static fn ($text): string => mb_strtolower( (string) preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $text), 'UTF-8' ); return $this; } /** * Makes the element's content with a line through. */ final public function lineThrough(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[9m%s\e[0m", $text); return $this; } /** * Makes the element's content invisible. */ final public function invisible(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[8m%s\e[0m", $text); return $this; } /** * Do not display element's content. */ final public function hidden(): self { return $this->with(['styles' => [ 'display' => 'hidden', ]]); } /** * Makes a line break before the element's content. */ final public function block(): self { return $this->with(['styles' => [ 'display' => 'block', ]]); } /** * Makes an element eligible to work with flex-1 element's style. */ final public function flex(): self { return $this->with(['styles' => [ 'display' => 'flex', ]]); } /** * Makes an element grow and shrink as needed, ignoring the initial size. */ final public function flex1(): self { return $this->with(['styles' => [ 'flex-1' => true, ]]); } /** * Justifies childs along the element with an equal amount of space between. */ final public function justifyBetween(): self { return $this->with(['styles' => [ 'justifyContent' => 'between', ]]); } /** * Justifies childs along the element with an equal amount of space between * each item and half around. */ final public function justifyAround(): self { return $this->with(['styles' => [ 'justifyContent' => 'around', ]]); } /** * Justifies childs along the element with an equal amount of space around each item. */ final public function justifyEvenly(): self { return $this->with(['styles' => [ 'justifyContent' => 'evenly', ]]); } /** * Justifies childs along the center of the container’s main axis. */ final public function justifyCenter(): self { return $this->with(['styles' => [ 'justifyContent' => 'center', ]]); } /** * Repeats the string given until it fills all the content. */ final public function contentRepeat(string $string): self { $string = preg_replace("/\[?'?([^'|\]]+)'?\]?/", '$1', $string) ?? ''; $this->textModifiers[__METHOD__] = static fn (): string => str_repeat($string, (int) floor(terminal()->width() / mb_strlen($string, 'UTF-8'))); return $this->with(['styles' => [ 'contentRepeat' => true, ]]); } /** * Prepends text to the content. */ final public function prepend(string $string): self { $this->textModifiers[__METHOD__] = static fn ($text): string => $string.$text; return $this; } /** * Appends text to the content. */ final public function append(string $string): self { $this->textModifiers[__METHOD__] = static fn ($text): string => $text.$string; return $this; } /** * Prepends the list style type to the content. */ final public function list(string $type, int $index = 0): self { if (! $this->element instanceof Ul && ! $this->element instanceof Ol && ! $this->element instanceof Li) { throw new InvalidStyle(sprintf( 'Style list-none cannot be used with %s', $this->element !== null ? $this->element::class : 'unknown element' )); } if (! $this->element instanceof Li) { return $this; } return match ($type) { 'square' => $this->prepend('▪ '), 'disc' => $this->prepend('• '), 'decimal' => $this->prepend(sprintf('%d. ', $index)), default => $this, }; } /** * Adds the given properties to the element. * * @param array<string, mixed> $properties */ public function with(array $properties): self { $this->properties = array_replace_recursive($this->properties, $properties); return $this; } /** * Sets the href property to the element. */ final public function href(string $href): self { $href = str_replace('%', '%%', $href); return $this->with(['href' => array_filter([$href])]); } /** * Formats a given string. */ final public function format(string $content): string { foreach ($this->textModifiers as $modifier) { $content = $modifier( $content, $this->properties['styles'] ?? [], $this->properties['parentStyles'] ?? [] ); } $content = $this->applyWidth($content); foreach ($this->styleModifiers as $modifier) { $content = $modifier($content, $this->properties['styles'] ?? []); } return $this->applyStyling($content); } /** * Get the format string including required styles. */ private function getFormatString(): string { $styles = []; /** @var array<int, string> $href */ $href = $this->properties['href'] ?? []; if ($href !== []) { $styles[] = sprintf('href=%s', array_pop($href)); } $colors = $this->properties['colors'] ?? []; foreach ($colors as $option => $content) { if (in_array($option, ['fg', 'bg'], true)) { $content = is_array($content) ? array_pop($content) : $content; $styles[] = "$option=$content"; } } $options = $this->properties['options'] ?? []; if ($options !== []) { $options = array_keys(array_filter( $options, fn ($option) => $option === true )); $styles[] = count($options) > 0 ? 'options='.implode(',', $options) : 'options=,'; } // If there are no styles we don't need extra tags if ($styles === []) { return '%s%s%s%s%s'; } return '%s<'.implode(';', $styles).'>%s%s%s</>%s'; } /** * Get the margins applied to the element. * * @return array{0: int, 1: int, 2: int, 3: int} */ private function getMargins(): array { $isFirstChild = (bool) $this->properties['isFirstChild']; $spaceY = $this->properties['parentStyles']['spaceY'] ?? []; $spaceY = ! $isFirstChild ? end($spaceY) : 0; $spaceX = $this->properties['parentStyles']['spaceX'] ?? []; $spaceX = ! $isFirstChild ? end($spaceX) : 0; return [ $spaceY > 0 ? $spaceY : $this->properties['styles']['mt'] ?? 0, $this->properties['styles']['mr'] ?? 0, $this->properties['styles']['mb'] ?? 0, $spaceX > 0 ? $spaceX : $this->properties['styles']['ml'] ?? 0, ]; } /** * Get the paddings applied to the element. * * @return array{0: int, 1: int, 2: int, 3: int} */ private function getPaddings(): array { return [ $this->properties['styles']['pt'] ?? 0, $this->properties['styles']['pr'] ?? 0, $this->properties['styles']['pb'] ?? 0, $this->properties['styles']['pl'] ?? 0, ]; } /** * It applies the correct width for the content. */ private function applyWidth(string $content): string { $styles = $this->properties['styles'] ?? []; $minWidth = $styles['minWidth'] ?? -1; $width = max($styles['width'] ?? -1, $minWidth); $maxWidth = $styles['maxWidth'] ?? 0; if ($width < 0) { return $content; } if ($width === 0) { return ''; } if (is_string($width)) { $width = self::calcWidthFromFraction( $width, $styles, $this->properties['parentStyles'] ?? [] ); } if ($maxWidth > 0) { $width = min($styles['maxWidth'], $width); } $width -= ($styles['pl'] ?? 0) + ($styles['pr'] ?? 0); $length = $this->getLength($content); preg_match_all("/\n+/", $content, $matches); $width *= count($matches[0] ?? []) + 1; $width += mb_strlen($matches[0][0] ?? '', 'UTF-8'); if ($length <= $width) { $space = $width - $length; return match ($styles['text-align'] ?? '') { 'right' => str_repeat(' ', $space).$content, 'center' => str_repeat(' ', (int) floor($space / 2)).$content.str_repeat(' ', (int) ceil($space / 2)), default => $content.str_repeat(' ', $space), }; } return self::trimText($content, $width); } /** * It applies the styling for the content. */ private function applyStyling(string $content): string { $display = $this->properties['styles']['display'] ?? 'inline'; if ($display === 'hidden') { return ''; } $isFirstChild = (bool) $this->properties['isFirstChild']; [$marginTop, $marginRight, $marginBottom, $marginLeft] = $this->getMargins(); [$paddingTop, $paddingRight, $paddingBottom, $paddingLeft] = $this->getPaddings(); $content = (string) preg_replace('/\r[ \t]?/', "\n", (string) preg_replace( '/\n/', str_repeat(' ', $marginRight + $paddingRight) ."\n". str_repeat(' ', $marginLeft + $paddingLeft), $content) ); $formatted = sprintf( $this->getFormatString(), str_repeat(' ', $marginLeft), str_repeat(' ', $paddingLeft), $content, str_repeat(' ', $paddingRight), str_repeat(' ', $marginRight), ); $empty = str_replace( $content, str_repeat(' ', $this->getLength($content)), $formatted ); $items = []; if (in_array($display, ['block', 'flex'], true) && ! $isFirstChild) { $items[] = "\n"; } if ($marginTop > 0) { $items[] = str_repeat("\n", $marginTop); } if ($paddingTop > 0) { $items[] = $empty."\n"; } $items[] = $formatted; if ($paddingBottom > 0) { $items[] = "\n".$empty; } if ($marginBottom > 0) { $items[] = str_repeat("\n", $marginBottom); } return implode('', $items); } /** * Get the length of the text provided without the styling tags. */ public function getLength(string $text = null): int { return mb_strlen(preg_replace( self::STYLING_REGEX, '', $text ?? $this->element?->toString() ?? '' ) ?? '', 'UTF-8'); } /** * Get the length of the element without margins. */ public function getInnerWidth(): int { $innerLength = $this->getLength(); [, $marginRight, , $marginLeft] = $this->getMargins(); return $innerLength - $marginLeft - $marginRight; } /** * Get the constant variant color from Color class. */ private function getColorVariant(string $color, int $variant): string { if ($variant > 0) { $color .= '-'.$variant; } if (StyleRepository::has($color)) { return StyleRepository::get($color)->getColor(); } $colorConstant = mb_strtoupper(str_replace('-', '_', $color), 'UTF-8'); if (! defined(Color::class."::$colorConstant")) { throw new ColorNotFound($colorConstant); } return constant(Color::class."::$colorConstant"); } /** * Calculates the width based on the fraction provided. * * @param array<string, int> $styles * @param array<string, array<int, int|string>> $parentStyles */ private static function calcWidthFromFraction(string $fraction, array $styles, array $parentStyles): int { $width = self::getParentWidth($parentStyles); preg_match('/(\d+)\/(\d+)/', $fraction, $matches); if (count($matches) !== 3 || $matches[2] === '0') { throw new InvalidStyle(sprintf('Style [%s] is invalid.', "w-$fraction")); } /** @@phpstan-ignore-next-line */ $width = (int) floor($width * $matches[1] / $matches[2]); $width -= ($styles['ml'] ?? 0) + ($styles['mr'] ?? 0); return $width; } /** * Gets the width of the parent element. * * @param array<string, array<int|string>> $styles */ public static function getParentWidth(array $styles): int { $width = terminal()->width(); foreach ($styles['width'] ?? [] as $index => $parentWidth) { $minWidth = (int) $styles['minWidth'][$index]; $maxWidth = (int) $styles['maxWidth'][$index]; $margins = (int) $styles['ml'][$index] + (int) $styles['mr'][$index]; $parentWidth = max($parentWidth, $minWidth); if ($parentWidth < 1) { $parentWidth = $width; } elseif (is_int($parentWidth)) { $parentWidth += $margins; } preg_match('/(\d+)\/(\d+)/', (string) $parentWidth, $matches); $width = count($matches) !== 3 ? (int) $parentWidth : (int) floor($width * $matches[1] / $matches[2]); //@phpstan-ignore-line if ($maxWidth > 0) { $width = min($maxWidth, $width); } $width -= $margins; $width -= (int) $styles['pl'][$index] + (int) $styles['pr'][$index]; } return $width; } /** * It trims the text properly ignoring all escape codes and * `<bg;fg;options>` tags. */ private static function trimText(string $text, int $width): string { preg_match_all(self::STYLING_REGEX, $text, $matches, PREG_OFFSET_CAPTURE); $text = rtrim(mb_strimwidth(preg_replace(self::STYLING_REGEX, '', $text) ?? '', 0, $width, '', 'UTF-8')); foreach ($matches[0] ?? [] as [$part, $index]) { $text = substr($text, 0, $index).$part.substr($text, $index, null); } return $text; } } PK 6n]K�"�o o "