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

MyIntervals / PHP-CSS-Parser / 13111676724

03 Feb 2025 10:42AM UTC coverage: 49.02% (+3.3%) from 45.68%
13111676724

Pull #871

github

web-flow
Merge 65afd70f6 into 1fad44a1b
Pull Request #871: [FEATURE] Add dedicated accessors for `OutputFormat`

143 of 143 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

925 of 1887 relevant lines covered (49.02%)

10.89 hits per line

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

98.38
/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
    public $sStringQuotingType = '"';
15

16
    /**
17
     * Output RGB colors in hash notation if possible
18
     *
19
     * @var string
20
     */
21
    public $bRGBHashNotation = 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
    public $bSemicolonAfterLastRule = 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 (e.g. `$oFormat->set('Space*Rules', "\n");`)
37
     */
38
    public $sSpaceAfterRuleName = ' ';
39

40
    /**
41
     * @var string
42
     */
43
    public $sSpaceBeforeRules = '';
44

45
    /**
46
     * @var string
47
     */
48
    public $sSpaceAfterRules = '';
49

50
    /**
51
     * @var string
52
     */
53
    public $sSpaceBetweenRules = '';
54

55
    /**
56
     * @var string
57
     */
58
    public $sSpaceBeforeBlocks = '';
59

60
    /**
61
     * @var string
62
     */
63
    public $sSpaceAfterBlocks = '';
64

65
    /**
66
     * @var string
67
     */
68
    public $sSpaceBetweenBlocks = "\n";
69

70
    /**
71
     * Content injected in and around at-rule blocks.
72
     *
73
     * @var string
74
     */
75
    public $sBeforeAtRuleBlock = '';
76

77
    /**
78
     * @var string
79
     */
80
    public $sAfterAtRuleBlock = '';
81

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

89
    /**
90
     * @var string
91
     */
92
    public $sSpaceAfterSelectorSeparator = ' ';
93

94
    /**
95
     * This is what’s printed after the comma of value lists
96
     *
97
     * @var string
98
     */
99
    public $sSpaceBeforeListArgumentSeparator = '';
100

101
    /**
102
     * @var string
103
     */
104
    public $sSpaceAfterListArgumentSeparator = '';
105

106
    /**
107
     * @var string
108
     */
109
    public $sSpaceBeforeOpeningBrace = ' ';
110

111
    /**
112
     * Content injected in and around declaration blocks.
113
     *
114
     * @var string
115
     */
116
    public $sBeforeDeclarationBlock = '';
117

118
    /**
119
     * @var string
120
     */
121
    public $sAfterDeclarationBlockSelectors = '';
122

123
    /**
124
     * @var string
125
     */
126
    public $sAfterDeclarationBlock = '';
127

128
    /**
129
     * Indentation character(s) per level. Only applicable if newlines are used in any of the spacing settings.
130
     *
131
     * @var string
132
     */
133
    public $sIndentation = "\t";
134

135
    /**
136
     * Output exceptions.
137
     *
138
     * @var bool
139
     */
140
    public $bIgnoreExceptions = false;
141

142
    /**
143
     * Render comments for lists and RuleSets
144
     *
145
     * @var bool
146
     */
147
    public $bRenderComments = false;
148

149
    /**
150
     * @var OutputFormatter|null
151
     */
152
    private $oFormatter = null;
153

154
    /**
155
     * @var OutputFormat|null
156
     */
157
    private $oNextLevelFormat = null;
158

159
    /**
160
     * @var int
161
     */
162
    private $iIndentationLevel = 0;
163

164
    public function __construct() {}
165

166
    /**
167
     * @return string|int|bool|null
168
     */
169
    public function get(string $sName)
19✔
170
    {
171
        $aVarPrefixes = ['a', 's', 'm', 'b', 'f', 'o', 'c', 'i'];
19✔
172
        foreach ($aVarPrefixes as $sPrefix) {
19✔
173
            $sFieldName = $sPrefix . \ucfirst($sName);
19✔
174
            if (isset($this->$sFieldName)) {
19✔
175
                return $this->$sFieldName;
19✔
176
            }
177
        }
178
        return null;
×
179
    }
180

181
    /**
182
     * @param array<array-key, string>|string $aNames
183
     * @param mixed $mValue
184
     *
185
     * @return self|false
186
     */
187
    public function set($aNames, $mValue)
8✔
188
    {
189
        $aVarPrefixes = ['a', 's', 'm', 'b', 'f', 'o', 'c', 'i'];
8✔
190
        if (\is_string($aNames) && \strpos($aNames, '*') !== false) {
8✔
191
            $aNames =
192
                [
193
                    \str_replace('*', 'Before', $aNames),
8✔
194
                    \str_replace('*', 'Between', $aNames),
8✔
195
                    \str_replace('*', 'After', $aNames),
8✔
196
                ];
197
        } elseif (!\is_array($aNames)) {
3✔
198
            $aNames = [$aNames];
3✔
199
        }
200
        foreach ($aVarPrefixes as $sPrefix) {
8✔
201
            $bDidReplace = false;
8✔
202
            foreach ($aNames as $sName) {
8✔
203
                $sFieldName = $sPrefix . \ucfirst($sName);
8✔
204
                if (isset($this->$sFieldName)) {
8✔
205
                    $this->$sFieldName = $mValue;
8✔
206
                    $bDidReplace = true;
8✔
207
                }
208
            }
209
            if ($bDidReplace) {
8✔
210
                return $this;
8✔
211
            }
212
        }
213
        // Break the chain so the user knows this option is invalid
214
        return false;
×
215
    }
216

217
    /**
218
     * @param array<array-key, mixed> $aArguments
219
     *
220
     * @return mixed
221
     *
222
     * @throws \Exception
223
     */
224
    public function __call(string $sMethodName, array $aArguments)
19✔
225
    {
226
        if (\method_exists(OutputFormatter::class, $sMethodName)) {
19✔
227
            return \call_user_func_array([$this->getFormatter(), $sMethodName], $aArguments);
19✔
228
        } else {
UNCOV
229
            throw new \Exception('Unknown OutputFormat method called: ' . $sMethodName);
×
230
        }
231
    }
232

233
    /**
234
     * @internal
235
     */
236
    public function getStringQuotingType(): string
20✔
237
    {
238
        return $this->sStringQuotingType;
20✔
239
    }
240

241
    /**
242
     * @return $this fluent interface
243
     */
244
    public function setStringQuotingType(string $quotingType): self
3✔
245
    {
246
        $this->sStringQuotingType = $quotingType;
3✔
247

248
        return $this;
3✔
249
    }
250

251
    /**
252
     * @internal
253
     */
254
    public function getRGBHashNotation(): bool
22✔
255
    {
256
        return $this->bRGBHashNotation;
22✔
257
    }
258

259
    /**
260
     * @return $this fluent interface
261
     */
262
    public function setRGBHashNotation(bool $rgbHashNotation): self
4✔
263
    {
264
        $this->bRGBHashNotation = $rgbHashNotation;
4✔
265

266
        return $this;
4✔
267
    }
268

269
    /**
270
     * @internal
271
     */
272
    public function getSemicolonAfterLastRule(): bool
3✔
273
    {
274
        return $this->bSemicolonAfterLastRule;
3✔
275
    }
276

277
    /**
278
     * @return $this fluent interface
279
     */
280
    public function setSemicolonAfterLastRule(bool $semicolonAfterLastRule): self
4✔
281
    {
282
        $this->bSemicolonAfterLastRule = $semicolonAfterLastRule;
4✔
283

284
        return $this;
4✔
285
    }
286

287
    /**
288
     * @internal
289
     */
290
    public function getSpaceAfterRuleName(): string
2✔
291
    {
292
        return $this->sSpaceAfterRuleName;
2✔
293
    }
294

295
    /**
296
     * @return $this fluent interface
297
     */
298
    public function setSpaceAfterRuleName(string $whitespace): self
6✔
299
    {
300
        $this->sSpaceAfterRuleName = $whitespace;
6✔
301

302
        return $this;
6✔
303
    }
304

305
    /**
306
     * @internal
307
     */
308
    public function getSpaceBeforeRules(): string
2✔
309
    {
310
        return $this->sSpaceBeforeRules;
2✔
311
    }
312

313
    /**
314
     * @return $this fluent interface
315
     */
316
    public function setSpaceBeforeRules(string $whitespace): self
2✔
317
    {
318
        $this->sSpaceBeforeRules = $whitespace;
2✔
319

320
        return $this;
2✔
321
    }
322

323
    /**
324
     * @internal
325
     */
326
    public function getSpaceAfterRules(): string
2✔
327
    {
328
        return $this->sSpaceAfterRules;
2✔
329
    }
330

331
    /**
332
     * @return $this fluent interface
333
     */
334
    public function setSpaceAfterRules(string $whitespace): self
2✔
335
    {
336
        $this->sSpaceAfterRules = $whitespace;
2✔
337

338
        return $this;
2✔
339
    }
340

341
    /**
342
     * @internal
343
     */
344
    public function getSpaceBetweenRules(): string
2✔
345
    {
346
        return $this->sSpaceBetweenRules;
2✔
347
    }
348

349
    /**
350
     * @return $this fluent interface
351
     */
352
    public function setSpaceBetweenRules(string $whitespace): self
2✔
353
    {
354
        $this->sSpaceBetweenRules = $whitespace;
2✔
355

356
        return $this;
2✔
357
    }
358

359
    /**
360
     * @internal
361
     */
362
    public function getSpaceBeforeBlocks(): string
2✔
363
    {
364
        return $this->sSpaceBeforeBlocks;
2✔
365
    }
366

367
    /**
368
     * @return $this fluent interface
369
     */
370
    public function setSpaceBeforeBlocks(string $whitespace): self
2✔
371
    {
372
        $this->sSpaceBeforeBlocks = $whitespace;
2✔
373

374
        return $this;
2✔
375
    }
376

377
    /**
378
     * @internal
379
     */
380
    public function getSpaceAfterBlocks(): string
2✔
381
    {
382
        return $this->sSpaceAfterBlocks;
2✔
383
    }
384

385
    /**
386
     * @return $this fluent interface
387
     */
388
    public function setSpaceAfterBlocks(string $whitespace): self
2✔
389
    {
390
        $this->sSpaceAfterBlocks = $whitespace;
2✔
391

392
        return $this;
2✔
393
    }
394

395
    /**
396
     * @internal
397
     */
398
    public function getSpaceBetweenBlocks(): string
2✔
399
    {
400
        return $this->sSpaceBetweenBlocks;
2✔
401
    }
402

403
    /**
404
     * @return $this fluent interface
405
     */
406
    public function setSpaceBetweenBlocks(string $whitespace): self
6✔
407
    {
408
        $this->sSpaceBetweenBlocks = $whitespace;
6✔
409

410
        return $this;
6✔
411
    }
412

413
    /**
414
     * @internal
415
     */
416
    public function getBeforeAtRuleBlock(): string
2✔
417
    {
418
        return $this->sBeforeAtRuleBlock;
2✔
419
    }
420

421
    /**
422
     * @return $this fluent interface
423
     */
424
    public function setBeforeAtRuleBlock(string $whitespace): self
2✔
425
    {
426
        $this->sBeforeAtRuleBlock = $whitespace;
2✔
427

428
        return $this;
2✔
429
    }
430

431
    /**
432
     * @internal
433
     */
434
    public function getAfterAtRuleBlock(): string
2✔
435
    {
436
        return $this->sAfterAtRuleBlock;
2✔
437
    }
438

439
    /**
440
     * @return $this fluent interface
441
     */
442
    public function setAfterAtRuleBlock(string $whitespace): self
2✔
443
    {
444
        $this->sAfterAtRuleBlock = $whitespace;
2✔
445

446
        return $this;
2✔
447
    }
448

449
    /**
450
     * @internal
451
     */
452
    public function getSpaceBeforeSelectorSeparator(): string
2✔
453
    {
454
        return $this->sSpaceBeforeSelectorSeparator;
2✔
455
    }
456

457
    /**
458
     * @return $this fluent interface
459
     */
460
    public function setSpaceBeforeSelectorSeparator(string $whitespace): self
2✔
461
    {
462
        $this->sSpaceBeforeSelectorSeparator = $whitespace;
2✔
463

464
        return $this;
2✔
465
    }
466

467
    /**
468
     * @internal
469
     */
470
    public function getSpaceAfterSelectorSeparator(): string
2✔
471
    {
472
        return $this->sSpaceAfterSelectorSeparator;
2✔
473
    }
474

475
    /**
476
     * @return $this fluent interface
477
     */
478
    public function setSpaceAfterSelectorSeparator(string $whitespace): self
6✔
479
    {
480
        $this->sSpaceAfterSelectorSeparator = $whitespace;
6✔
481

482
        return $this;
6✔
483
    }
484

485
    /**
486
     * @internal
487
     */
488
    public function getSpaceBeforeListArgumentSeparator(): string
2✔
489
    {
490
        return $this->sSpaceBeforeListArgumentSeparator;
2✔
491
    }
492

493
    /**
494
     * @return $this fluent interface
495
     */
496
    public function setSpaceBeforeListArgumentSeparator(string $whitespace): self
2✔
497
    {
498
        $this->sSpaceBeforeListArgumentSeparator = $whitespace;
2✔
499

500
        return $this;
2✔
501
    }
502

503
    /**
504
     * @internal
505
     */
506
    public function getSpaceAfterListArgumentSeparator(): string
2✔
507
    {
508
        return $this->sSpaceAfterListArgumentSeparator;
2✔
509
    }
510

511
    /**
512
     * @return $this fluent interface
513
     */
514
    public function setSpaceAfterListArgumentSeparator(string $whitespace): self
3✔
515
    {
516
        $this->sSpaceAfterListArgumentSeparator = $whitespace;
3✔
517

518
        return $this;
3✔
519
    }
520

521
    /**
522
     * @internal
523
     */
524
    public function getSpaceBeforeOpeningBrace(): string
2✔
525
    {
526
        return $this->sSpaceBeforeOpeningBrace;
2✔
527
    }
528

529
    /**
530
     * @return $this fluent interface
531
     */
532
    public function setSpaceBeforeOpeningBrace(string $whitespace): self
6✔
533
    {
534
        $this->sSpaceBeforeOpeningBrace = $whitespace;
6✔
535

536
        return $this;
6✔
537
    }
538

539
    /**
540
     * @internal
541
     */
542
    public function getBeforeDeclarationBlock(): string
2✔
543
    {
544
        return $this->sBeforeDeclarationBlock;
2✔
545
    }
546

547
    /**
548
     * @return $this fluent interface
549
     */
550
    public function setBeforeDeclarationBlock(string $whitespace): self
2✔
551
    {
552
        $this->sBeforeDeclarationBlock = $whitespace;
2✔
553

554
        return $this;
2✔
555
    }
556

557
    /**
558
     * @internal
559
     */
560
    public function getAfterDeclarationBlockSelectors(): string
2✔
561
    {
562
        return $this->sAfterDeclarationBlockSelectors;
2✔
563
    }
564

565
    /**
566
     * @return $this fluent interface
567
     */
568
    public function setAfterDeclarationBlockSelectors(string $whitespace): self
2✔
569
    {
570
        $this->sAfterDeclarationBlockSelectors = $whitespace;
2✔
571

572
        return $this;
2✔
573
    }
574

575
    /**
576
     * @internal
577
     */
578
    public function getAfterDeclarationBlock(): string
2✔
579
    {
580
        return $this->sAfterDeclarationBlock;
2✔
581
    }
582

583
    /**
584
     * @return $this fluent interface
585
     */
586
    public function setAfterDeclarationBlock(string $whitespace): self
2✔
587
    {
588
        $this->sAfterDeclarationBlock = $whitespace;
2✔
589

590
        return $this;
2✔
591
    }
592

593
    /**
594
     * @internal
595
     */
596
    public function getIndentation(): string
13✔
597
    {
598
        return $this->sIndentation;
13✔
599
    }
600

601
    /**
602
     * @return $this fluent interface
603
     */
604
    public function setIndentation(string $sIndentation): self
16✔
605
    {
606
        $this->sIndentation = $sIndentation;
16✔
607

608
        return $this;
16✔
609
    }
610

611
    /**
612
     * @internal
613
     */
614
    public function getIgnoreExceptions(): bool
4✔
615
    {
616
        return $this->bIgnoreExceptions;
4✔
617
    }
618

619
    /**
620
     * @return $this fluent interface
621
     */
622
    public function setIgnoreExceptions(bool $bIgnoreExceptions): self
6✔
623
    {
624
        $this->bIgnoreExceptions = $bIgnoreExceptions;
6✔
625

626
        return $this;
6✔
627
    }
628

629
    /**
630
     * @internal
631
     */
632
    public function getRenderComments(): bool
3✔
633
    {
634
        return $this->bRenderComments;
3✔
635
    }
636

637
    /**
638
     * @return $this fluent interface
639
     */
640
    public function setRenderComments(bool $bRenderComments): self
7✔
641
    {
642
        $this->bRenderComments = $bRenderComments;
7✔
643

644
        return $this;
7✔
645
    }
646

647
    /**
648
     * @internal
649
     */
650
    public function getIndentationLevel(): int
22✔
651
    {
652
        return $this->iIndentationLevel;
22✔
653
    }
654

655
    /**
656
     * @return $this fluent interface
657
     */
658
    public function setIndentationLevel(int $iIndentationLevel): self
3✔
659
    {
660
        $this->iIndentationLevel = $iIndentationLevel;
3✔
661

662
        return $this;
3✔
663
    }
664

665
    /**
666
     * @return $this fluent interface
667
     */
668
    public function indentWithTabs(int $numberOfTabs = 1): self
6✔
669
    {
670
        return $this->setIndentation(\str_repeat("\t", $numberOfTabs));
6✔
671
    }
672

673
    /**
674
     * @return $this fluent interface
675
     */
676
    public function indentWithSpaces(int $numberOfSpaces = 2): self
7✔
677
    {
678
        return $this->setIndentation(\str_repeat(' ', $numberOfSpaces));
7✔
679
    }
680

681
    public function nextLevel(): self
22✔
682
    {
683
        if ($this->oNextLevelFormat === null) {
22✔
684
            $this->oNextLevelFormat = clone $this;
22✔
685
            $this->oNextLevelFormat->iIndentationLevel++;
22✔
686
            $this->oNextLevelFormat->oFormatter = null;
22✔
687
        }
688
        return $this->oNextLevelFormat;
22✔
689
    }
690

691
    public function beLenient(): void
1✔
692
    {
693
        $this->bIgnoreExceptions = true;
1✔
694
    }
1✔
695

696
    public function getFormatter(): OutputFormatter
21✔
697
    {
698
        if ($this->oFormatter === null) {
21✔
699
            $this->oFormatter = new OutputFormatter($this);
21✔
700
        }
701
        return $this->oFormatter;
21✔
702
    }
703

704
    /**
705
     * Creates an instance of this class without any particular formatting settings.
706
     */
707
    public static function create(): self
20✔
708
    {
709
        return new OutputFormat();
20✔
710
    }
711

712
    /**
713
     * Creates an instance of this class with a preset for compact formatting.
714
     */
715
    public static function createCompact(): self
3✔
716
    {
717
        $format = self::create();
3✔
718
        $format->set('Space*Rules', '')
3✔
719
            ->set('Space*Blocks', '')
3✔
720
            ->setSpaceAfterRuleName('')
3✔
721
            ->setSpaceBeforeOpeningBrace('')
3✔
722
            ->setSpaceAfterSelectorSeparator('')
3✔
723
            ->setRenderComments(false);
3✔
724
        return $format;
3✔
725
    }
726

727
    /**
728
     * Creates an instance of this class with a preset for pretty formatting.
729
     */
730
    public static function createPretty(): self
3✔
731
    {
732
        $format = self::create();
3✔
733
        $format->set('Space*Rules', "\n")
3✔
734
            ->set('Space*Blocks', "\n")
3✔
735
            ->setSpaceBetweenBlocks("\n\n")
3✔
736
            ->set('SpaceAfterListArgumentSeparator', ['default' => '', ',' => ' '])
3✔
737
            ->setRenderComments(true);
3✔
738
        return $format;
3✔
739
    }
740
}
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