All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
754 lines
16 KiB
PHP
754 lines
16 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace Sabberworm\CSS;
|
||
|
||
final class OutputFormat
|
||
{
|
||
/**
|
||
* Value format: `"` means double-quote, `'` means single-quote
|
||
*
|
||
* @var non-empty-string
|
||
*/
|
||
private $stringQuotingType = '"';
|
||
|
||
/**
|
||
* Output RGB colors in hash notation if possible
|
||
*
|
||
* @var bool
|
||
*/
|
||
private $usesRgbHashNotation = true;
|
||
|
||
/**
|
||
* Declaration format
|
||
*
|
||
* Semicolon after the last rule of a declaration block can be omitted. To do that, set this false.
|
||
*
|
||
* @var bool
|
||
*/
|
||
private $renderSemicolonAfterLastRule = true;
|
||
|
||
/**
|
||
* Spacing
|
||
* Note that these strings are not sanity-checked: the value should only consist of whitespace
|
||
* Any newline character will be indented according to the current level.
|
||
* The triples (After, Before, Between) can be set using a wildcard
|
||
* (e.g. `$outputFormat->set('Space*Rules', "\n");`)
|
||
*
|
||
* @var string
|
||
*/
|
||
private $spaceAfterRuleName = ' ';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $spaceBeforeRules = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $spaceAfterRules = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $spaceBetweenRules = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $spaceBeforeBlocks = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $spaceAfterBlocks = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $spaceBetweenBlocks = "\n";
|
||
|
||
/**
|
||
* Content injected in and around at-rule blocks.
|
||
*
|
||
* @var string
|
||
*/
|
||
private $contentBeforeAtRuleBlock = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $contentAfterAtRuleBlock = '';
|
||
|
||
/**
|
||
* This is what’s printed before and after the comma if a declaration block contains multiple selectors.
|
||
*
|
||
* @var string
|
||
*/
|
||
private $spaceBeforeSelectorSeparator = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $spaceAfterSelectorSeparator = ' ';
|
||
|
||
/**
|
||
* This is what’s inserted before the separator in value lists, by default.
|
||
*
|
||
* @var string
|
||
*/
|
||
private $spaceBeforeListArgumentSeparator = '';
|
||
|
||
/**
|
||
* Keys are separators (e.g. `,`). Values are the space sequence to insert, or an empty string.
|
||
*
|
||
* @var array<non-empty-string, string>
|
||
*/
|
||
private $spaceBeforeListArgumentSeparators = [];
|
||
|
||
/**
|
||
* This is what’s inserted after the separator in value lists, by default.
|
||
*
|
||
* @var string
|
||
*/
|
||
private $spaceAfterListArgumentSeparator = '';
|
||
|
||
/**
|
||
* Keys are separators (e.g. `,`). Values are the space sequence to insert, or an empty string.
|
||
*
|
||
* @var array<non-empty-string, string>
|
||
*/
|
||
private $spaceAfterListArgumentSeparators = [];
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $spaceBeforeOpeningBrace = ' ';
|
||
|
||
/**
|
||
* Content injected in and around declaration blocks.
|
||
*
|
||
* @var string
|
||
*/
|
||
private $contentBeforeDeclarationBlock = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $contentAfterDeclarationBlockSelectors = '';
|
||
|
||
/**
|
||
* @var string
|
||
*/
|
||
private $contentAfterDeclarationBlock = '';
|
||
|
||
/**
|
||
* Indentation character(s) per level. Only applicable if newlines are used in any of the spacing settings.
|
||
*
|
||
* @var string
|
||
*/
|
||
private $indentation = "\t";
|
||
|
||
/**
|
||
* Output exceptions.
|
||
*
|
||
* @var bool
|
||
*/
|
||
private $shouldIgnoreExceptions = false;
|
||
|
||
/**
|
||
* Render comments for lists and RuleSets
|
||
*
|
||
* @var bool
|
||
*/
|
||
private $shouldRenderComments = false;
|
||
|
||
/**
|
||
* @var OutputFormatter|null
|
||
*/
|
||
private $outputFormatter;
|
||
|
||
/**
|
||
* @var OutputFormat|null
|
||
*/
|
||
private $nextLevelFormat;
|
||
|
||
/**
|
||
* @var int<0, max>
|
||
*/
|
||
private $indentationLevel = 0;
|
||
|
||
/**
|
||
* @return non-empty-string
|
||
*
|
||
* @internal
|
||
*/
|
||
public function getStringQuotingType(): string
|
||
{
|
||
return $this->stringQuotingType;
|
||
}
|
||
|
||
/**
|
||
* @param non-empty-string $quotingType
|
||
*
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setStringQuotingType(string $quotingType): self
|
||
{
|
||
$this->stringQuotingType = $quotingType;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function usesRgbHashNotation(): bool
|
||
{
|
||
return $this->usesRgbHashNotation;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setRGBHashNotation(bool $usesRgbHashNotation): self
|
||
{
|
||
$this->usesRgbHashNotation = $usesRgbHashNotation;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function shouldRenderSemicolonAfterLastRule(): bool
|
||
{
|
||
return $this->renderSemicolonAfterLastRule;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSemicolonAfterLastRule(bool $renderSemicolonAfterLastRule): self
|
||
{
|
||
$this->renderSemicolonAfterLastRule = $renderSemicolonAfterLastRule;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceAfterRuleName(): string
|
||
{
|
||
return $this->spaceAfterRuleName;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceAfterRuleName(string $whitespace): self
|
||
{
|
||
$this->spaceAfterRuleName = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceBeforeRules(): string
|
||
{
|
||
return $this->spaceBeforeRules;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceBeforeRules(string $whitespace): self
|
||
{
|
||
$this->spaceBeforeRules = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceAfterRules(): string
|
||
{
|
||
return $this->spaceAfterRules;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceAfterRules(string $whitespace): self
|
||
{
|
||
$this->spaceAfterRules = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceBetweenRules(): string
|
||
{
|
||
return $this->spaceBetweenRules;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceBetweenRules(string $whitespace): self
|
||
{
|
||
$this->spaceBetweenRules = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceBeforeBlocks(): string
|
||
{
|
||
return $this->spaceBeforeBlocks;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceBeforeBlocks(string $whitespace): self
|
||
{
|
||
$this->spaceBeforeBlocks = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceAfterBlocks(): string
|
||
{
|
||
return $this->spaceAfterBlocks;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceAfterBlocks(string $whitespace): self
|
||
{
|
||
$this->spaceAfterBlocks = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceBetweenBlocks(): string
|
||
{
|
||
return $this->spaceBetweenBlocks;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceBetweenBlocks(string $whitespace): self
|
||
{
|
||
$this->spaceBetweenBlocks = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getContentBeforeAtRuleBlock(): string
|
||
{
|
||
return $this->contentBeforeAtRuleBlock;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setBeforeAtRuleBlock(string $content): self
|
||
{
|
||
$this->contentBeforeAtRuleBlock = $content;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getContentAfterAtRuleBlock(): string
|
||
{
|
||
return $this->contentAfterAtRuleBlock;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setAfterAtRuleBlock(string $content): self
|
||
{
|
||
$this->contentAfterAtRuleBlock = $content;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceBeforeSelectorSeparator(): string
|
||
{
|
||
return $this->spaceBeforeSelectorSeparator;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceBeforeSelectorSeparator(string $whitespace): self
|
||
{
|
||
$this->spaceBeforeSelectorSeparator = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceAfterSelectorSeparator(): string
|
||
{
|
||
return $this->spaceAfterSelectorSeparator;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceAfterSelectorSeparator(string $whitespace): self
|
||
{
|
||
$this->spaceAfterSelectorSeparator = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceBeforeListArgumentSeparator(): string
|
||
{
|
||
return $this->spaceBeforeListArgumentSeparator;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceBeforeListArgumentSeparator(string $whitespace): self
|
||
{
|
||
$this->spaceBeforeListArgumentSeparator = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @return array<non-empty-string, string>
|
||
*
|
||
* @internal
|
||
*/
|
||
public function getSpaceBeforeListArgumentSeparators(): array
|
||
{
|
||
return $this->spaceBeforeListArgumentSeparators;
|
||
}
|
||
|
||
/**
|
||
* @param array<non-empty-string, string> $separatorSpaces
|
||
*
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceBeforeListArgumentSeparators(array $separatorSpaces): self
|
||
{
|
||
$this->spaceBeforeListArgumentSeparators = $separatorSpaces;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceAfterListArgumentSeparator(): string
|
||
{
|
||
return $this->spaceAfterListArgumentSeparator;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceAfterListArgumentSeparator(string $whitespace): self
|
||
{
|
||
$this->spaceAfterListArgumentSeparator = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @return array<non-empty-string, string>
|
||
*
|
||
* @internal
|
||
*/
|
||
public function getSpaceAfterListArgumentSeparators(): array
|
||
{
|
||
return $this->spaceAfterListArgumentSeparators;
|
||
}
|
||
|
||
/**
|
||
* @param array<non-empty-string, string> $separatorSpaces
|
||
*
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceAfterListArgumentSeparators(array $separatorSpaces): self
|
||
{
|
||
$this->spaceAfterListArgumentSeparators = $separatorSpaces;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getSpaceBeforeOpeningBrace(): string
|
||
{
|
||
return $this->spaceBeforeOpeningBrace;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setSpaceBeforeOpeningBrace(string $whitespace): self
|
||
{
|
||
$this->spaceBeforeOpeningBrace = $whitespace;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getContentBeforeDeclarationBlock(): string
|
||
{
|
||
return $this->contentBeforeDeclarationBlock;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setBeforeDeclarationBlock(string $content): self
|
||
{
|
||
$this->contentBeforeDeclarationBlock = $content;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getContentAfterDeclarationBlockSelectors(): string
|
||
{
|
||
return $this->contentAfterDeclarationBlockSelectors;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setAfterDeclarationBlockSelectors(string $content): self
|
||
{
|
||
$this->contentAfterDeclarationBlockSelectors = $content;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getContentAfterDeclarationBlock(): string
|
||
{
|
||
return $this->contentAfterDeclarationBlock;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setAfterDeclarationBlock(string $content): self
|
||
{
|
||
$this->contentAfterDeclarationBlock = $content;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function getIndentation(): string
|
||
{
|
||
return $this->indentation;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setIndentation(string $indentation): self
|
||
{
|
||
$this->indentation = $indentation;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function shouldIgnoreExceptions(): bool
|
||
{
|
||
return $this->shouldIgnoreExceptions;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setIgnoreExceptions(bool $ignoreExceptions): self
|
||
{
|
||
$this->shouldIgnoreExceptions = $ignoreExceptions;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @internal
|
||
*/
|
||
public function shouldRenderComments(): bool
|
||
{
|
||
return $this->shouldRenderComments;
|
||
}
|
||
|
||
/**
|
||
* @return $this fluent interface
|
||
*/
|
||
public function setRenderComments(bool $renderComments): self
|
||
{
|
||
$this->shouldRenderComments = $renderComments;
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* @return int<0, max>
|
||
*
|
||
* @internal
|
||
*/
|
||
public function getIndentationLevel(): int
|
||
{
|
||
return $this->indentationLevel;
|
||
}
|
||
|
||
/**
|
||
* @param int<1, max> $numberOfTabs
|
||
*
|
||
* @return $this fluent interface
|
||
*/
|
||
public function indentWithTabs(int $numberOfTabs = 1): self
|
||
{
|
||
return $this->setIndentation(\str_repeat("\t", $numberOfTabs));
|
||
}
|
||
|
||
/**
|
||
* @param int<1, max> $numberOfSpaces
|
||
*
|
||
* @return $this fluent interface
|
||
*/
|
||
public function indentWithSpaces(int $numberOfSpaces = 2): self
|
||
{
|
||
return $this->setIndentation(\str_repeat(' ', $numberOfSpaces));
|
||
}
|
||
|
||
/**
|
||
* @internal since V8.8.0
|
||
*/
|
||
public function nextLevel(): self
|
||
{
|
||
if ($this->nextLevelFormat === null) {
|
||
$this->nextLevelFormat = clone $this;
|
||
$this->nextLevelFormat->indentationLevel++;
|
||
$this->nextLevelFormat->outputFormatter = null;
|
||
}
|
||
return $this->nextLevelFormat;
|
||
}
|
||
|
||
public function beLenient(): void
|
||
{
|
||
$this->shouldIgnoreExceptions = true;
|
||
}
|
||
|
||
/**
|
||
* @internal since 8.8.0
|
||
*/
|
||
public function getFormatter(): OutputFormatter
|
||
{
|
||
if ($this->outputFormatter === null) {
|
||
$this->outputFormatter = new OutputFormatter($this);
|
||
}
|
||
|
||
return $this->outputFormatter;
|
||
}
|
||
|
||
/**
|
||
* Creates an instance of this class without any particular formatting settings.
|
||
*/
|
||
public static function create(): self
|
||
{
|
||
return new OutputFormat();
|
||
}
|
||
|
||
/**
|
||
* Creates an instance of this class with a preset for compact formatting.
|
||
*/
|
||
public static function createCompact(): self
|
||
{
|
||
$format = self::create();
|
||
$format
|
||
->setSpaceBeforeRules('')
|
||
->setSpaceBetweenRules('')
|
||
->setSpaceAfterRules('')
|
||
->setSpaceBeforeBlocks('')
|
||
->setSpaceBetweenBlocks('')
|
||
->setSpaceAfterBlocks('')
|
||
->setSpaceAfterRuleName('')
|
||
->setSpaceBeforeOpeningBrace('')
|
||
->setSpaceAfterSelectorSeparator('')
|
||
->setSemicolonAfterLastRule(false)
|
||
->setRenderComments(false);
|
||
|
||
return $format;
|
||
}
|
||
|
||
/**
|
||
* Creates an instance of this class with a preset for pretty formatting.
|
||
*/
|
||
public static function createPretty(): self
|
||
{
|
||
$format = self::create();
|
||
$format
|
||
->setSpaceBeforeRules("\n")
|
||
->setSpaceBetweenRules("\n")
|
||
->setSpaceAfterRules("\n")
|
||
->setSpaceBeforeBlocks("\n")
|
||
->setSpaceBetweenBlocks("\n\n")
|
||
->setSpaceAfterBlocks("\n")
|
||
->setSpaceAfterListArgumentSeparators([',' => ' '])
|
||
->setRenderComments(true);
|
||
|
||
return $format;
|
||
}
|
||
}
|