• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MyIntervals / PHP-CSS-Parser / 28995132880

09 Jul 2026 04:57AM UTC coverage: 71.517% (-1.1%) from 72.604%
28995132880

Pull #1484

github

web-flow
Merge 67ad74e99 into 3316f7374
Pull Request #1484: Remove `thecodingmachine/safe` dependency

25 of 78 new or added lines in 12 files covered. (32.05%)

7 existing lines in 5 files now uncovered.

1622 of 2268 relevant lines covered (71.52%)

37.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

44.9
/src/Value/CSSString.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Sabberworm\CSS\Value;
6

7
use Sabberworm\CSS\OutputFormat;
8
use Sabberworm\CSS\Parsing\ParserState;
9
use Sabberworm\CSS\Parsing\SourceException;
10
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
11
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
12
use Sabberworm\CSS\ShortClassNameProvider;
13

14
/**
15
 * This class is a wrapper for quoted strings to distinguish them from keywords.
16
 *
17
 * `CSSString`s always output with double quotes.
18
 */
19
class CSSString extends PrimitiveValue
20
{
21
    use ShortClassNameProvider;
22

23
    /**
24
     * @var string
25
     */
26
    private $string;
27

28
    /**
29
     * @param int<1, max>|null $lineNumber
30
     */
31
    public function __construct(string $string, ?int $lineNumber = null)
10✔
32
    {
33
        $this->string = $string;
10✔
34
        parent::__construct($lineNumber);
10✔
35
    }
10✔
36

37
    /**
38
     * @throws SourceException
39
     * @throws UnexpectedEOFException
40
     * @throws UnexpectedTokenException
41
     *
42
     * @internal since V8.8.0
43
     */
44
    public static function parse(ParserState $parserState): CSSString
×
45
    {
46
        $begin = $parserState->peek();
×
47
        $quote = null;
×
48
        if ($begin === "'") {
×
49
            $quote = "'";
×
50
        } elseif ($begin === '"') {
×
51
            $quote = '"';
×
52
        }
53
        if ($quote !== null) {
×
54
            $parserState->consume($quote);
×
55
        }
56
        $result = '';
×
57
        if ($quote === null) {
×
58
            // Unquoted strings end in whitespace or with braces, brackets, parentheses
NEW
59
            while (true) {
×
60
                /** @phpstan-ignore theCodingMachineSafe.function */
NEW
61
                $matchResult = \preg_match('/[\\s{}()<>\\[\\]]/isu', $parserState->peek());
×
NEW
62
                if ($matchResult === false) {
×
NEW
63
                    throw new \RuntimeException('Unexpected error');
×
64
                }
NEW
65
                if ($matchResult !== 0) {
×
NEW
66
                    break;
×
67
                }
UNCOV
68
                $result .= $parserState->parseCharacter(false);
×
69
            }
70
        } else {
71
            while (!$parserState->comes($quote)) {
×
72
                $content = $parserState->parseCharacter(false);
×
73
                if ($content === null) {
×
74
                    throw new SourceException(
×
75
                        "Non-well-formed quoted string {$parserState->peek(3)}",
×
76
                        $parserState->currentLine()
×
77
                    );
78
                }
79
                $result .= $content;
×
80
            }
81
            $parserState->consume($quote);
×
82
        }
83
        return new CSSString($result, $parserState->currentLine());
×
84
    }
85

86
    public function setString(string $string): void
1✔
87
    {
88
        $this->string = $string;
1✔
89
    }
1✔
90

91
    public function getString(): string
2✔
92
    {
93
        return $this->string;
2✔
94
    }
95

96
    /**
97
     * @return non-empty-string
98
     */
99
    public function render(OutputFormat $outputFormat): string
2✔
100
    {
101
        return $outputFormat->getStringQuotingType()
2✔
102
            . $this->escape($this->string, $outputFormat)
2✔
103
            . $outputFormat->getStringQuotingType();
2✔
104
    }
105

106
    /**
107
     * @return array<string, bool|int|float|string|array<mixed>|null>
108
     *
109
     * @internal
110
     */
111
    public function getArrayRepresentation(): array
2✔
112
    {
113
        return [
114
            'class' => $this->getShortClassName(),
2✔
115
            // We're using the term "contents" here to make the difference to the class more clear.
116
            'contents' => $this->string,
2✔
117
        ];
118
    }
119

120
    private function escape(string $string, OutputFormat $outputFormat): string
2✔
121
    {
122
        $charactersToEscape = '\\';
2✔
123
        $charactersToEscape .= ($outputFormat->getStringQuotingType() === '"' ? '"' : "'");
2✔
124
        $withEscapedQuotes = \addcslashes($string, $charactersToEscape);
2✔
125

126
        $withNewlineEncoded = \str_replace("\n", '\\A', $withEscapedQuotes);
2✔
127

128
        return $withNewlineEncoded;
2✔
129
    }
130
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc