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

MyIntervals / PHP-CSS-Parser / 13725214804

07 Mar 2025 04:43PM UTC coverage: 54.834% (-0.8%) from 55.626%
13725214804

push

github

web-flow
[CLEANUP] Use the explicit `OutputFormat` setters in the tests (#1106)

The `set()` method will be removed soon.

Also unify the tests a bit.

Part of #1103

1038 of 1893 relevant lines covered (54.83%)

12.2 hits per line

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

86.93
/src/OutputFormat.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Sabberworm\CSS;
6

7
class OutputFormat
8
{
9
    /**
10
     * Value format: `"` means double-quote, `'` means single-quote
11
     *
12
     * @var string
13
     */
14
    private $stringQuotingType = '"';
15

16
    /**
17
     * Output RGB colors in hash notation if possible
18
     *
19
     * @var bool
20
     */
21
    private $usesRgbHashNotation = true;
22

23
    /**
24
     * Declaration format
25
     *
26
     * Semicolon after the last rule of a declaration block can be omitted. To do that, set this false.
27
     *
28
     * @var bool
29
     */
30
    private $renderSemicolonAfterLastRule = true;
31

32
    /**
33
     * Spacing
34
     * Note that these strings are not sanity-checked: the value should only consist of whitespace
35
     * Any newline character will be indented according to the current level.
36
     * The triples (After, Before, Between) can be set using a wildcard
37
     * (e.g. `$outputFormat->set('Space*Rules', "\n");`)
38
     *
39
     * @var string
40
     */
41
    private $spaceAfterRuleName = ' ';
42

43
    /**
44
     * @var string
45
     */
46
    private $sSpaceBeforeRules = '';
47

48
    /**
49
     * @var string
50
     */
51
    private $sSpaceAfterRules = '';
52

53
    /**
54
     * @var string
55
     */
56
    private $sSpaceBetweenRules = '';
57

58
    /**
59
     * @var string
60
     */
61
    private $sSpaceBeforeBlocks = '';
62

63
    /**
64
     * @var string
65
     */
66
    private $sSpaceAfterBlocks = '';
67

68
    /**
69
     * @var string
70
     */
71
    private $sSpaceBetweenBlocks = "\n";
72

73
    /**
74
     * Content injected in and around at-rule blocks.
75
     *
76
     * @var string
77
     */
78
    private $sBeforeAtRuleBlock = '';
79

80
    /**
81
     * @var string
82
     */
83
    private $sAfterAtRuleBlock = '';
84

85
    /**
86
     * This is what’s printed before and after the comma if a declaration block contains multiple selectors.
87
     *
88
     * @var string
89
     */
90
    private $sSpaceBeforeSelectorSeparator = '';
91

92
    /**
93
     * @var string
94
     */
95
    private $sSpaceAfterSelectorSeparator = ' ';
96

97
    /**
98
     * This is what’s inserted before the separator in value lists, by default.
99
     *
100
     * @var string
101
     */
102
    private $sSpaceBeforeListArgumentSeparator = '';
103

104
    /**
105
     * Keys are separators (e.g. `,`).  Values are the space sequence to insert, or an empty string.
106
     *
107
     * @var array<non-empty-string, string>
108
     */
109
    private $aSpaceBeforeListArgumentSeparators = [];
110

111
    /**
112
     * This is what’s inserted after the separator in value lists, by default.
113
     *
114
     * @var string
115
     */
116
    private $sSpaceAfterListArgumentSeparator = '';
117

118
    /**
119
     * Keys are separators (e.g. `,`).  Values are the space sequence to insert, or an empty string.
120
     *
121
     * @var array<non-empty-string, string>
122
     */
123
    private $aSpaceAfterListArgumentSeparators = [];
124

125
    /**
126
     * @var string
127
     */
128
    private $sSpaceBeforeOpeningBrace = ' ';
129

130
    /**
131
     * Content injected in and around declaration blocks.
132
     *
133
     * @var string
134
     */
135
    private $sBeforeDeclarationBlock = '';
136

137
    /**
138
     * @var string
139
     */
140
    private $sAfterDeclarationBlockSelectors = '';
141

142
    /**
143
     * @var string
144
     */
145
    private $sAfterDeclarationBlock = '';
146

147
    /**
148
     * Indentation character(s) per level. Only applicable if newlines are used in any of the spacing settings.
149
     *
150
     * @var string
151
     */
152
    private $sIndentation = "\t";
153

154
    /**
155
     * Output exceptions.
156
     *
157
     * @var bool
158
     */
159
    private $bIgnoreExceptions = false;
160

161
    /**
162
     * Render comments for lists and RuleSets
163
     *
164
     * @var bool
165
     */
166
    private $bRenderComments = false;
167

168
    /**
169
     * @var OutputFormatter|null
170
     */
171
    private $outputFormatter;
172

173
    /**
174
     * @var OutputFormat|null
175
     */
176
    private $nextLevelFormat;
177

178
    /**
179
     * @var int
180
     */
181
    private $iIndentationLevel = 0;
182

183
    public function __construct() {}
184

185
    /**
186
     * @return string|int|bool|null
187
     */
188
    public function get(string $name)
×
189
    {
190
        $aVarPrefixes = ['a', 's', 'm', 'b', 'f', 'o', 'c', 'i'];
×
191
        foreach ($aVarPrefixes as $prefix) {
×
192
            $sFieldName = $prefix . \ucfirst($name);
×
193
            if (isset($this->$sFieldName)) {
×
194
                return $this->$sFieldName;
×
195
            }
196
        }
197
        return null;
×
198
    }
199

200
    /**
201
     * @param array<array-key, string>|string $names
202
     * @param mixed $value
203
     *
204
     * @return self|false
205
     */
206
    public function set($names, $value)
×
207
    {
208
        $aVarPrefixes = ['a', 's', 'm', 'b', 'f', 'o', 'c', 'i'];
×
209
        if (\is_string($names) && \strpos($names, '*') !== false) {
×
210
            $names =
211
                [
212
                    \str_replace('*', 'Before', $names),
×
213
                    \str_replace('*', 'Between', $names),
×
214
                    \str_replace('*', 'After', $names),
×
215
                ];
216
        } elseif (!\is_array($names)) {
×
217
            $names = [$names];
×
218
        }
219
        foreach ($aVarPrefixes as $prefix) {
×
220
            $bDidReplace = false;
×
221
            foreach ($names as $name) {
×
222
                $sFieldName = $prefix . \ucfirst($name);
×
223
                if (isset($this->$sFieldName)) {
×
224
                    $this->$sFieldName = $value;
×
225
                    $bDidReplace = true;
×
226
                }
227
            }
228
            if ($bDidReplace) {
×
229
                return $this;
×
230
            }
231
        }
232
        // Break the chain so the user knows this option is invalid
233
        return false;
×
234
    }
235

236
    /**
237
     * @param non-empty-string $sMethodName
238
     * @param array<array-key, mixed> $arguments
239
     *
240
     * @return mixed
241
     *
242
     * @throws \Exception
243
     */
244
    public function __call(string $sMethodName, array $arguments)
20✔
245
    {
246
        if (\method_exists(OutputFormatter::class, $sMethodName)) {
20✔
247
            // @deprecated since 8.8.0, will be removed in 9.0.0. Call the method on the formatter directly instead.
248
            return \call_user_func_array([$this->getFormatter(), $sMethodName], $arguments);
20✔
249
        } else {
250
            throw new \Exception('Unknown OutputFormat method called: ' . $sMethodName);
×
251
        }
252
    }
253

254
    /**
255
     * @internal
256
     */
257
    public function getStringQuotingType(): string
21✔
258
    {
259
        return $this->stringQuotingType;
21✔
260
    }
261

262
    /**
263
     * @return $this fluent interface
264
     */
265
    public function setStringQuotingType(string $quotingType): self
3✔
266
    {
267
        $this->stringQuotingType = $quotingType;
3✔
268

269
        return $this;
3✔
270
    }
271

272
    /**
273
     * @internal
274
     */
275
    public function usesRgbHashNotation(): bool
23✔
276
    {
277
        return $this->usesRgbHashNotation;
23✔
278
    }
279

280
    /**
281
     * @return $this fluent interface
282
     */
283
    public function setRGBHashNotation(bool $usesRgbHashNotation): self
4✔
284
    {
285
        $this->usesRgbHashNotation = $usesRgbHashNotation;
4✔
286

287
        return $this;
4✔
288
    }
289

290
    /**
291
     * @internal
292
     */
293
    public function shouldRenderSemicolonAfterLastRule(): bool
23✔
294
    {
295
        return $this->renderSemicolonAfterLastRule;
23✔
296
    }
297

298
    /**
299
     * @return $this fluent interface
300
     */
301
    public function setSemicolonAfterLastRule(bool $renderSemicolonAfterLastRule): self
4✔
302
    {
303
        $this->renderSemicolonAfterLastRule = $renderSemicolonAfterLastRule;
4✔
304

305
        return $this;
4✔
306
    }
307

308
    /**
309
     * @internal
310
     */
311
    public function getSpaceAfterRuleName(): string
25✔
312
    {
313
        return $this->spaceAfterRuleName;
25✔
314
    }
315

316
    /**
317
     * @return $this fluent interface
318
     */
319
    public function setSpaceAfterRuleName(string $whitespace): self
20✔
320
    {
321
        $this->spaceAfterRuleName = $whitespace;
20✔
322

323
        return $this;
20✔
324
    }
325

326
    /**
327
     * @internal
328
     */
329
    public function getSpaceBeforeRules(): string
24✔
330
    {
331
        return $this->sSpaceBeforeRules;
24✔
332
    }
333

334
    /**
335
     * @return $this fluent interface
336
     */
337
    public function setSpaceBeforeRules(string $whitespace): self
35✔
338
    {
339
        $this->sSpaceBeforeRules = $whitespace;
35✔
340

341
        return $this;
35✔
342
    }
343

344
    /**
345
     * @internal
346
     */
347
    public function getSpaceAfterRules(): string
24✔
348
    {
349
        return $this->sSpaceAfterRules;
24✔
350
    }
351

352
    /**
353
     * @return $this fluent interface
354
     */
355
    public function setSpaceAfterRules(string $whitespace): self
35✔
356
    {
357
        $this->sSpaceAfterRules = $whitespace;
35✔
358

359
        return $this;
35✔
360
    }
361

362
    /**
363
     * @internal
364
     */
365
    public function getSpaceBetweenRules(): string
22✔
366
    {
367
        return $this->sSpaceBetweenRules;
22✔
368
    }
369

370
    /**
371
     * @return $this fluent interface
372
     */
373
    public function setSpaceBetweenRules(string $whitespace): self
35✔
374
    {
375
        $this->sSpaceBetweenRules = $whitespace;
35✔
376

377
        return $this;
35✔
378
    }
379

380
    /**
381
     * @internal
382
     */
383
    public function getSpaceBeforeBlocks(): string
24✔
384
    {
385
        return $this->sSpaceBeforeBlocks;
24✔
386
    }
387

388
    /**
389
     * @return $this fluent interface
390
     */
391
    public function setSpaceBeforeBlocks(string $whitespace): self
35✔
392
    {
393
        $this->sSpaceBeforeBlocks = $whitespace;
35✔
394

395
        return $this;
35✔
396
    }
397

398
    /**
399
     * @internal
400
     */
401
    public function getSpaceAfterBlocks(): string
24✔
402
    {
403
        return $this->sSpaceAfterBlocks;
24✔
404
    }
405

406
    /**
407
     * @return $this fluent interface
408
     */
409
    public function setSpaceAfterBlocks(string $whitespace): self
35✔
410
    {
411
        $this->sSpaceAfterBlocks = $whitespace;
35✔
412

413
        return $this;
35✔
414
    }
415

416
    /**
417
     * @internal
418
     */
419
    public function getSpaceBetweenBlocks(): string
23✔
420
    {
421
        return $this->sSpaceBetweenBlocks;
23✔
422
    }
423

424
    /**
425
     * @return $this fluent interface
426
     */
427
    public function setSpaceBetweenBlocks(string $whitespace): self
36✔
428
    {
429
        $this->sSpaceBetweenBlocks = $whitespace;
36✔
430

431
        return $this;
36✔
432
    }
433

434
    /**
435
     * @internal
436
     */
437
    public function getBeforeAtRuleBlock(): string
22✔
438
    {
439
        return $this->sBeforeAtRuleBlock;
22✔
440
    }
441

442
    /**
443
     * @return $this fluent interface
444
     */
445
    public function setBeforeAtRuleBlock(string $content): self
2✔
446
    {
447
        $this->sBeforeAtRuleBlock = $content;
2✔
448

449
        return $this;
2✔
450
    }
451

452
    /**
453
     * @internal
454
     */
455
    public function getAfterAtRuleBlock(): string
22✔
456
    {
457
        return $this->sAfterAtRuleBlock;
22✔
458
    }
459

460
    /**
461
     * @return $this fluent interface
462
     */
463
    public function setAfterAtRuleBlock(string $content): self
2✔
464
    {
465
        $this->sAfterAtRuleBlock = $content;
2✔
466

467
        return $this;
2✔
468
    }
469

470
    /**
471
     * @internal
472
     */
473
    public function getSpaceBeforeSelectorSeparator(): string
22✔
474
    {
475
        return $this->sSpaceBeforeSelectorSeparator;
22✔
476
    }
477

478
    /**
479
     * @return $this fluent interface
480
     */
481
    public function setSpaceBeforeSelectorSeparator(string $whitespace): self
2✔
482
    {
483
        $this->sSpaceBeforeSelectorSeparator = $whitespace;
2✔
484

485
        return $this;
2✔
486
    }
487

488
    /**
489
     * @internal
490
     */
491
    public function getSpaceAfterSelectorSeparator(): string
24✔
492
    {
493
        return $this->sSpaceAfterSelectorSeparator;
24✔
494
    }
495

496
    /**
497
     * @return $this fluent interface
498
     */
499
    public function setSpaceAfterSelectorSeparator(string $whitespace): self
19✔
500
    {
501
        $this->sSpaceAfterSelectorSeparator = $whitespace;
19✔
502

503
        return $this;
19✔
504
    }
505

506
    /**
507
     * @internal
508
     */
509
    public function getSpaceBeforeListArgumentSeparator(): string
20✔
510
    {
511
        return $this->sSpaceBeforeListArgumentSeparator;
20✔
512
    }
513

514
    /**
515
     * @return $this fluent interface
516
     */
517
    public function setSpaceBeforeListArgumentSeparator(string $whitespace): self
2✔
518
    {
519
        $this->sSpaceBeforeListArgumentSeparator = $whitespace;
2✔
520

521
        return $this;
2✔
522
    }
523

524
    /**
525
     * @return array<non-empty-string, string>
526
     *
527
     * @internal
528
     */
529
    public function getSpaceBeforeListArgumentSeparators(): array
20✔
530
    {
531
        return $this->aSpaceBeforeListArgumentSeparators;
20✔
532
    }
533

534
    /**
535
     * @param array<non-empty-string, string> $separatorSpaces
536
     *
537
     * @return $this fluent interface
538
     */
539
    public function setSpaceBeforeListArgumentSeparators(array $separatorSpaces): self
2✔
540
    {
541
        $this->aSpaceBeforeListArgumentSeparators = $separatorSpaces;
2✔
542

543
        return $this;
2✔
544
    }
545

546
    /**
547
     * @internal
548
     */
549
    public function getSpaceAfterListArgumentSeparator(): string
19✔
550
    {
551
        return $this->sSpaceAfterListArgumentSeparator;
19✔
552
    }
553

554
    /**
555
     * @return $this fluent interface
556
     */
557
    public function setSpaceAfterListArgumentSeparator(string $whitespace): self
4✔
558
    {
559
        $this->sSpaceAfterListArgumentSeparator = $whitespace;
4✔
560

561
        return $this;
4✔
562
    }
563

564
    /**
565
     * @return array<non-empty-string, string>
566
     *
567
     * @internal
568
     */
569
    public function getSpaceAfterListArgumentSeparators(): array
22✔
570
    {
571
        return $this->aSpaceAfterListArgumentSeparators;
22✔
572
    }
573

574
    /**
575
     * @param array<non-empty-string, string> $separatorSpaces
576
     *
577
     * @return $this fluent interface
578
     */
579
    public function setSpaceAfterListArgumentSeparators(array $separatorSpaces): self
19✔
580
    {
581
        $this->aSpaceAfterListArgumentSeparators = $separatorSpaces;
19✔
582

583
        return $this;
19✔
584
    }
585

586
    /**
587
     * @internal
588
     */
589
    public function getSpaceBeforeOpeningBrace(): string
24✔
590
    {
591
        return $this->sSpaceBeforeOpeningBrace;
24✔
592
    }
593

594
    /**
595
     * @return $this fluent interface
596
     */
597
    public function setSpaceBeforeOpeningBrace(string $whitespace): self
19✔
598
    {
599
        $this->sSpaceBeforeOpeningBrace = $whitespace;
19✔
600

601
        return $this;
19✔
602
    }
603

604
    /**
605
     * @internal
606
     */
607
    public function getBeforeDeclarationBlock(): string
22✔
608
    {
609
        return $this->sBeforeDeclarationBlock;
22✔
610
    }
611

612
    /**
613
     * @return $this fluent interface
614
     */
615
    public function setBeforeDeclarationBlock(string $content): self
2✔
616
    {
617
        $this->sBeforeDeclarationBlock = $content;
2✔
618

619
        return $this;
2✔
620
    }
621

622
    /**
623
     * @internal
624
     */
625
    public function getAfterDeclarationBlockSelectors(): string
22✔
626
    {
627
        return $this->sAfterDeclarationBlockSelectors;
22✔
628
    }
629

630
    /**
631
     * @return $this fluent interface
632
     */
633
    public function setAfterDeclarationBlockSelectors(string $content): self
2✔
634
    {
635
        $this->sAfterDeclarationBlockSelectors = $content;
2✔
636

637
        return $this;
2✔
638
    }
639

640
    /**
641
     * @internal
642
     */
643
    public function getAfterDeclarationBlock(): string
22✔
644
    {
645
        return $this->sAfterDeclarationBlock;
22✔
646
    }
647

648
    /**
649
     * @return $this fluent interface
650
     */
651
    public function setAfterDeclarationBlock(string $content): self
2✔
652
    {
653
        $this->sAfterDeclarationBlock = $content;
2✔
654

655
        return $this;
2✔
656
    }
657

658
    /**
659
     * @internal
660
     */
661
    public function getIndentation(): string
33✔
662
    {
663
        return $this->sIndentation;
33✔
664
    }
665

666
    /**
667
     * @return $this fluent interface
668
     */
669
    public function setIndentation(string $indentation): self
16✔
670
    {
671
        $this->sIndentation = $indentation;
16✔
672

673
        return $this;
16✔
674
    }
675

676
    /**
677
     * @internal
678
     */
679
    public function getIgnoreExceptions(): bool
24✔
680
    {
681
        return $this->bIgnoreExceptions;
24✔
682
    }
683

684
    /**
685
     * @return $this fluent interface
686
     */
687
    public function setIgnoreExceptions(bool $ignoreExceptions): self
6✔
688
    {
689
        $this->bIgnoreExceptions = $ignoreExceptions;
6✔
690

691
        return $this;
6✔
692
    }
693

694
    /**
695
     * @internal
696
     */
697
    public function getRenderComments(): bool
25✔
698
    {
699
        return $this->bRenderComments;
25✔
700
    }
701

702
    /**
703
     * @return $this fluent interface
704
     */
705
    public function setRenderComments(bool $renderComments): self
33✔
706
    {
707
        $this->bRenderComments = $renderComments;
33✔
708

709
        return $this;
33✔
710
    }
711

712
    /**
713
     * @internal
714
     */
715
    public function getIndentationLevel(): int
22✔
716
    {
717
        return $this->iIndentationLevel;
22✔
718
    }
719

720
    /**
721
     * @return $this fluent interface
722
     */
723
    public function indentWithTabs(int $numberOfTabs = 1): self
6✔
724
    {
725
        return $this->setIndentation(\str_repeat("\t", $numberOfTabs));
6✔
726
    }
727

728
    /**
729
     * @return $this fluent interface
730
     */
731
    public function indentWithSpaces(int $numberOfSpaces = 2): self
7✔
732
    {
733
        return $this->setIndentation(\str_repeat(' ', $numberOfSpaces));
7✔
734
    }
735

736
    /**
737
     * @internal since V8.8.0
738
     */
739
    public function nextLevel(): self
25✔
740
    {
741
        if ($this->nextLevelFormat === null) {
25✔
742
            $this->nextLevelFormat = clone $this;
25✔
743
            $this->nextLevelFormat->iIndentationLevel++;
25✔
744
            $this->nextLevelFormat->outputFormatter = null;
25✔
745
        }
746
        return $this->nextLevelFormat;
25✔
747
    }
748

749
    public function beLenient(): void
1✔
750
    {
751
        $this->bIgnoreExceptions = true;
1✔
752
    }
1✔
753

754
    /**
755
     * @internal since 8.8.0
756
     */
757
    public function getFormatter(): OutputFormatter
23✔
758
    {
759
        if ($this->outputFormatter === null) {
23✔
760
            $this->outputFormatter = new OutputFormatter($this);
23✔
761
        }
762

763
        return $this->outputFormatter;
23✔
764
    }
765

766
    /**
767
     * Creates an instance of this class without any particular formatting settings.
768
     */
769
    public static function create(): self
48✔
770
    {
771
        return new OutputFormat();
48✔
772
    }
773

774
    /**
775
     * Creates an instance of this class with a preset for compact formatting.
776
     */
777
    public static function createCompact(): self
16✔
778
    {
779
        $format = self::create();
16✔
780
        $format
781
            ->setSpaceBeforeRules('')
16✔
782
            ->setSpaceBetweenRules('')
16✔
783
            ->setSpaceAfterRules('')
16✔
784
            ->setSpaceBeforeBlocks('')
16✔
785
            ->setSpaceBetweenBlocks('')
16✔
786
            ->setSpaceAfterBlocks('')
16✔
787
            ->setSpaceAfterRuleName('')
16✔
788
            ->setSpaceBeforeOpeningBrace('')
16✔
789
            ->setSpaceAfterSelectorSeparator('')
16✔
790
            ->setRenderComments(false);
16✔
791

792
        return $format;
16✔
793
    }
794

795
    /**
796
     * Creates an instance of this class with a preset for pretty formatting.
797
     */
798
    public static function createPretty(): self
16✔
799
    {
800
        $format = self::create();
16✔
801
        $format
802
            ->setSpaceBeforeRules("\n")
16✔
803
            ->setSpaceBetweenRules("\n")
16✔
804
            ->setSpaceAfterRules("\n")
16✔
805
            ->setSpaceBeforeBlocks("\n")
16✔
806
            ->setSpaceBetweenBlocks("\n\n")
16✔
807
            ->setSpaceAfterBlocks("\n")
16✔
808
            ->setSpaceAfterListArgumentSeparators([',' => ' '])
16✔
809
            ->setRenderComments(true);
16✔
810

811
        return $format;
16✔
812
    }
813
}
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

© 2025 Coveralls, Inc