← Back
Editing: OutputFormatter.php
<?php declare(strict_types=1); namespace Sabberworm\CSS; use Sabberworm\CSS\Comment\Commentable; use Sabberworm\CSS\Parsing\OutputException; /** * @internal since 8.8.0 */ class OutputFormatter { /** * @var OutputFormat */ private $outputFormat; public function __construct(OutputFormat $outputFormat) { $this->outputFormat = $outputFormat; } /** * @param non-empty-string $name * * @throws \InvalidArgumentException */ public function space(string $name): string { switch ($name) { case 'AfterRuleName': $spaceString = $this->outputFormat->getSpaceAfterRuleName(); break; case 'BeforeRules': $spaceString = $this->outputFormat->getSpaceBeforeRules(); break; case 'AfterRules': $spaceString = $this->outputFormat->getSpaceAfterRules(); break; case 'BetweenRules': $spaceString = $this->outputFormat->getSpaceBetweenRules(); break; case 'BeforeBlocks': $spaceString = $this->outputFormat->getSpaceBeforeBlocks(); break; case 'AfterBlocks': $spaceString = $this->outputFormat->getSpaceAfterBlocks(); break; case 'BetweenBlocks': $spaceString = $this->outputFormat->getSpaceBetweenBlocks(); break; case 'BeforeSelectorSeparator': $spaceString = $this->outputFormat->getSpaceBeforeSelectorSeparator(); break; case 'AfterSelectorSeparator': $spaceString = $this->outputFormat->getSpaceAfterSelectorSeparator(); break; case 'BeforeOpeningBrace': $spaceString = $this->outputFormat->getSpaceBeforeOpeningBrace(); break; case 'BeforeListArgumentSeparator': $spaceString = $this->outputFormat->getSpaceBeforeListArgumentSeparator(); break; case 'AfterListArgumentSeparator': $spaceString = $this->outputFormat->getSpaceAfterListArgumentSeparator(); break; default: throw new \InvalidArgumentException("Unknown space type: $name", 1740049248); } return $this->prepareSpace($spaceString); } public function spaceAfterRuleName(): string { return $this->space('AfterRuleName'); } public function spaceBeforeRules(): string { return $this->space('BeforeRules'); } public function spaceAfterRules(): string { return $this->space('AfterRules'); } public function spaceBetweenRules(): string { return $this->space('BetweenRules'); } public function spaceBeforeBlocks(): string { return $this->space('BeforeBlocks'); } public function spaceAfterBlocks(): string { return $this->space('AfterBlocks'); } public function spaceBetweenBlocks(): string { return $this->space('BetweenBlocks'); } public function spaceBeforeSelectorSeparator(): string { return $this->space('BeforeSelectorSeparator'); } public function spaceAfterSelectorSeparator(): string { return $this->space('AfterSelectorSeparator'); } /** * @param non-empty-string $separator */ public function spaceBeforeListArgumentSeparator(string $separator): string { $spaceForSeparator = $this->outputFormat->getSpaceBeforeListArgumentSeparators(); return $spaceForSeparator[$separator] ?? $this->space('BeforeListArgumentSeparator'); } /** * @param non-empty-string $separator */ public function spaceAfterListArgumentSeparator(string $separator): string { $spaceForSeparator = $this->outputFormat->getSpaceAfterListArgumentSeparators(); return $spaceForSeparator[$separator] ?? $this->space('AfterListArgumentSeparator'); } public function spaceBeforeOpeningBrace(): string { return $this->space('BeforeOpeningBrace'); } /** * Runs the given code, either swallowing or passing exceptions, depending on the `ignoreExceptions` setting. */ public function safely(callable $callable): ?string { if ($this->outputFormat->shouldIgnoreExceptions()) { // If output exceptions are ignored, run the code with exception guards try { return $callable(); } catch (OutputException $e) { return null; } // Do nothing } else { // Run the code as-is return $callable(); } } /** * Clone of the `implode` function, but calls `render` with the current output format. * * @param array<array-key, Renderable|string> $values */ public function implode(string $separator, array $values, bool $increaseLevel = false): string { $result = ''; $outputFormat = $this->outputFormat; if ($increaseLevel) { $outputFormat = $outputFormat->nextLevel(); } $isFirst = true; foreach ($values as $value) { if ($isFirst) { $isFirst = false; } else { $result .= $separator; } if ($value instanceof Renderable) { $result .= $value->render($outputFormat); } else { $result .= $value; } } return $result; } public function removeLastSemicolon(string $string): string { if ($this->outputFormat->shouldRenderSemicolonAfterLastRule()) { return $string; } $parts = \explode(';', $string); if (\count($parts) < 2) { return $parts[0]; } $lastPart = \array_pop($parts); $nextToLastPart = \array_pop($parts); \array_push($parts, $nextToLastPart . $lastPart); return \implode(';', $parts); } public function comments(Commentable $commentable): string { if (!$this->outputFormat->shouldRenderComments()) { return ''; } $result = ''; $comments = $commentable->getComments(); $lastCommentIndex = \count($comments) - 1; foreach ($comments as $i => $comment) { $result .= $comment->render($this->outputFormat); $result .= $i === $lastCommentIndex ? $this->spaceAfterBlocks() : $this->spaceBetweenBlocks(); } return $result; } private function prepareSpace(string $spaceString): string { return \str_replace("\n", "\n" . $this->indent(), $spaceString); } private function indent(): string { return \str_repeat($this->outputFormat->getIndentation(), $this->outputFormat->getIndentationLevel()); } }
Save File
Cancel