Passed
Push — add/6 ( 1ceb7c...3ff08f )
by
unknown
09:22 queued 04:37
created

Nested   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 177
rs 9.68
c 0
b 0
f 0
wmc 34

7 Methods

Rating   Name   Duplication   Size   Complexity  
C adjustAllChildren() 0 41 12
A blockLines() 0 16 4
A __construct() 0 10 1
B block() 0 37 9
A blockSelectors() 0 7 1
A blockChildren() 0 13 6
A indentStr() 0 5 1
1
<?php
2
/**
3
 * SCSSPHP
4
 *
5
 * @copyright 2012-2018 Leaf Corcoran
6
 *
7
 * @license http://opensource.org/licenses/MIT MIT
8
 *
9
 * @link http://leafo.github.io/scssphp
10
 */
11
12
namespace Leafo\ScssPhp\Formatter;
13
14
use Leafo\ScssPhp\Formatter;
15
use Leafo\ScssPhp\Formatter\OutputBlock;
16
17
/**
18
 * Nested formatter
19
 *
20
 * @author Leaf Corcoran <[email protected]>
21
 */
22
class Nested extends Formatter
23
{
24
    /**
25
     * @var integer
26
     */
27
    private $depth;
28
29
    /**
30
     * {@inheritdoc}
31
     */
32
    public function __construct()
33
    {
34
        $this->indentLevel = 0;
35
        $this->indentChar = '  ';
36
        $this->break = "\n";
37
        $this->open = ' {';
38
        $this->close = ' }';
39
        $this->tagSeparator = ', ';
40
        $this->assignSeparator = ': ';
41
        $this->keepSemicolons = true;
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    protected function indentStr()
48
    {
49
        $n = $this->depth - 1;
50
51
        return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    protected function blockLines(OutputBlock $block)
58
    {
59
        $inner = $this->indentStr();
60
61
        $glue = $this->break . $inner;
62
63
        foreach ($block->lines as $index => $line) {
64
            if (substr($line, 0, 2) === '/*') {
65
                $block->lines[$index] = preg_replace('/(\r|\n)+/', $glue, $line);
66
            }
67
        }
68
69
        $this->write($inner . implode($glue, $block->lines));
70
71
        if (! empty($block->children)) {
72
            $this->write($this->break);
73
        }
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    protected function blockSelectors(OutputBlock $block)
80
    {
81
        $inner = $this->indentStr();
82
83
        $this->write($inner
84
            . implode($this->tagSeparator, $block->selectors)
85
            . $this->open . $this->break);
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    protected function blockChildren(OutputBlock $block)
92
    {
93
        foreach ($block->children as $i => $child) {
94
            $this->block($child);
95
96
            if ($i < count($block->children) - 1) {
97
                $this->write($this->break);
98
99
                if (isset($block->children[$i + 1])) {
100
                    $next = $block->children[$i + 1];
101
102
                    if ($next->depth === max($block->depth, 1) && $child->depth >= $next->depth) {
103
                        $this->write($this->break);
104
                    }
105
                }
106
            }
107
        }
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    protected function block(OutputBlock $block)
114
    {
115
        if ($block->type === 'root') {
116
            $this->adjustAllChildren($block);
117
        }
118
119
        if (empty($block->lines) && empty($block->children)) {
120
            return;
121
        }
122
123
        $this->currentBlock = $block;
124
125
126
        $this->depth = $block->depth;
127
128
        if (! empty($block->selectors)) {
129
            $this->blockSelectors($block);
130
131
            $this->indentLevel++;
132
        }
133
134
        if (! empty($block->lines)) {
135
            $this->blockLines($block);
136
        }
137
138
        if (! empty($block->children)) {
139
            $this->blockChildren($block);
140
        }
141
142
        if (! empty($block->selectors)) {
143
            $this->indentLevel--;
144
145
            $this->write($this->close);
146
        }
147
148
        if ($block->type === 'root') {
149
            $this->write($this->break);
150
        }
151
    }
152
153
    /**
154
     * Adjust the depths of all children, depth first
155
     *
156
     * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
157
     */
158
    private function adjustAllChildren(OutputBlock $block)
159
    {
160
        // flatten empty nested blocks
161
        $children = [];
162
163
        foreach ($block->children as $i => $child) {
164
            if (empty($child->lines) && empty($child->children)) {
165
                if (isset($block->children[$i + 1])) {
166
                    $block->children[$i + 1]->depth = $child->depth;
167
                }
168
169
                continue;
170
            }
171
172
            $children[] = $child;
173
        }
174
175
        $count = count($children);
176
177
        for ($i = 0; $i < $count; $i++) {
178
            $depth = $children[$i]->depth;
179
            $j = $i + 1;
180
181
            if (isset($children[$j]) && $depth < $children[$j]->depth) {
182
                $childDepth = $children[$j]->depth;
183
184
                for (; $j < $count; $j++) {
185
                    if ($depth < $children[$j]->depth && $childDepth >= $children[$j]->depth) {
186
                        $children[$j]->depth = $depth + 1;
187
                    }
188
                }
189
            }
190
        }
191
192
        $block->children = $children;
193
194
        // make relative to parent
195
        foreach ($block->children as $child) {
196
            $this->adjustAllChildren($child);
197
198
            $child->depth = $child->depth - $block->depth;
199
        }
200
    }
201
}
202