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

Formatter   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 252
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 69
dl 0
loc 252
rs 10
c 0
b 0
f 0
wmc 25

9 Methods

Rating   Name   Duplication   Size   Complexity  
B block() 0 32 8
A stripSemicolon() 0 10 4
A blockSelectors() 0 7 1
A format() 0 17 2
A indentStr() 0 3 1
A write() 0 22 4
A blockChildren() 0 4 2
A property() 0 3 1
A blockLines() 0 10 2
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;
13
14
use Leafo\ScssPhp\Formatter\OutputBlock;
15
use Leafo\ScssPhp\SourceMap\SourceMapGenerator;
16
17
/**
18
 * Base formatter
19
 *
20
 * @author Leaf Corcoran <[email protected]>
21
 */
22
abstract class Formatter
23
{
24
    /**
25
     * @var integer
26
     */
27
    public $indentLevel;
28
29
    /**
30
     * @var string
31
     */
32
    public $indentChar;
33
34
    /**
35
     * @var string
36
     */
37
    public $break;
38
39
    /**
40
     * @var string
41
     */
42
    public $open;
43
44
    /**
45
     * @var string
46
     */
47
    public $close;
48
49
    /**
50
     * @var string
51
     */
52
    public $tagSeparator;
53
54
    /**
55
     * @var string
56
     */
57
    public $assignSeparator;
58
59
    /**
60
     * @var boolean
61
     */
62
    public $keepSemicolons;
63
64
    /**
65
     * @var \Leafo\ScssPhp\Formatter\OutputBlock
66
     */
67
    protected $currentBlock;
68
69
    /**
70
     * @var integer
71
     */
72
    protected $currentLine;
73
74
    /**
75
     * @var integer
76
     */
77
    protected $currentColumn;
78
79
    /**
80
     * @var \Leafo\ScssPhp\SourceMap\SourceMapGenerator
81
     */
82
    protected $sourceMapGenerator;
83
84
    /**
85
     * Initialize formatter
86
     *
87
     * @api
88
     */
89
    abstract public function __construct();
90
91
    /**
92
     * Return indentation (whitespace)
93
     *
94
     * @return string
95
     */
96
    protected function indentStr()
97
    {
98
        return '';
99
    }
100
101
    /**
102
     * Return property assignment
103
     *
104
     * @api
105
     *
106
     * @param string $name
107
     * @param mixed  $value
108
     *
109
     * @return string
110
     */
111
    public function property($name, $value)
112
    {
113
        return rtrim($name) . $this->assignSeparator . $value . ';';
114
    }
115
116
    /**
117
     * Strip semi-colon appended by property(); it's a separator, not a terminator
118
     *
119
     * @api
120
     *
121
     * @param array $lines
122
     */
123
    public function stripSemicolon(&$lines)
124
    {
125
        if ($this->keepSemicolons) {
126
            return;
127
        }
128
129
        if (($count = count($lines))
130
            && substr($lines[$count - 1], -1) === ';'
131
        ) {
132
            $lines[$count - 1] = substr($lines[$count - 1], 0, -1);
133
        }
134
    }
135
136
    /**
137
     * Output lines inside a block
138
     *
139
     * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
140
     */
141
    protected function blockLines(OutputBlock $block)
142
    {
143
        $inner = $this->indentStr();
144
145
        $glue = $this->break . $inner;
146
147
        $this->write($inner . implode($glue, $block->lines));
148
149
        if (! empty($block->children)) {
150
            $this->write($this->break);
151
        }
152
    }
153
154
    /**
155
     * Output block selectors
156
     *
157
     * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
158
     */
159
    protected function blockSelectors(OutputBlock $block)
160
    {
161
        $inner = $this->indentStr();
162
163
        $this->write($inner
164
            . implode($this->tagSeparator, $block->selectors)
165
            . $this->open . $this->break);
166
    }
167
168
    /**
169
     * Output block children
170
     *
171
     * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
172
     */
173
    protected function blockChildren(OutputBlock $block)
174
    {
175
        foreach ($block->children as $child) {
176
            $this->block($child);
177
        }
178
    }
179
180
    /**
181
     * Output non-empty block
182
     *
183
     * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
184
     */
185
    protected function block(OutputBlock $block)
186
    {
187
        if (empty($block->lines) && empty($block->children)) {
188
            return;
189
        }
190
191
        $this->currentBlock = $block;
192
193
        $pre = $this->indentStr();
194
195
        if (! empty($block->selectors)) {
196
            $this->blockSelectors($block);
197
198
            $this->indentLevel++;
199
        }
200
201
        if (! empty($block->lines)) {
202
            $this->blockLines($block);
203
        }
204
205
        if (! empty($block->children)) {
206
            $this->blockChildren($block);
207
        }
208
209
        if (! empty($block->selectors)) {
210
            $this->indentLevel--;
211
212
            if (empty($block->children)) {
213
                $this->write($this->break);
214
            }
215
216
            $this->write($pre . $this->close . $this->break);
217
        }
218
    }
219
220
    /**
221
     * Entry point to formatting a block
222
     *
223
     * @api
224
     *
225
     * @param \Leafo\ScssPhp\Formatter\OutputBlock             $block              An abstract syntax tree
226
     * @param \Leafo\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator
227
     *
228
     * @return string
229
     */
230
    public function format(OutputBlock $block, SourceMapGenerator $sourceMapGenerator = null)
231
    {
232
        $this->sourceMapGenerator = null;
233
234
        if ($sourceMapGenerator) {
235
            $this->currentLine = 1;
236
            $this->currentColumn = 0;
237
            $this->sourceMapGenerator = $sourceMapGenerator;
238
        }
239
240
        ob_start();
241
242
        $this->block($block);
243
244
        $out = ob_get_clean();
245
246
        return $out;
247
    }
248
249
    /**
250
     * @param string $str
251
     */
252
    protected function write($str)
253
    {
254
        if ($this->sourceMapGenerator) {
255
            $this->sourceMapGenerator->addMapping(
256
                $this->currentLine,
257
                $this->currentColumn,
258
                $this->currentBlock->sourceLine,
259
                $this->currentBlock->sourceColumn - 1, //columns from parser are off by one
260
                $this->currentBlock->sourceName
261
            );
262
263
            $lines = explode("\n", $str);
264
            $lineCount = count($lines);
265
            $this->currentLine += $lineCount-1;
266
267
            $lastLine = array_pop($lines);
268
269
            $this->currentColumn = ($lineCount === 1 ? $this->currentColumn : 0) + strlen($lastLine);
270
        }
271
272
        echo $str;
273
    }
274
}
275