See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]
1 <?php 2 3 /** 4 * SCSSPHP 5 * 6 * @copyright 2012-2020 Leaf Corcoran 7 * 8 * @license http://opensource.org/licenses/MIT MIT 9 * 10 * @link http://scssphp.github.io/scssphp 11 */ 12 13 namespace ScssPhp\ScssPhp\Formatter; 14 15 use ScssPhp\ScssPhp\Formatter; 16 use ScssPhp\ScssPhp\Type; 17 18 /** 19 * Nested formatter 20 * 21 * @author Leaf Corcoran <leafot@gmail.com> 22 * 23 * @deprecated since 1.4.0. Use the Expanded formatter instead. 24 * 25 * @internal 26 */ 27 class Nested extends Formatter 28 { 29 /** 30 * @var int 31 */ 32 private $depth; 33 34 /** 35 * {@inheritdoc} 36 */ 37 public function __construct() 38 { 39 @trigger_error('The Nested formatter is deprecated since 1.4.0. Use the Expanded formatter instead.', E_USER_DEPRECATED); 40 41 $this->indentLevel = 0; 42 $this->indentChar = ' '; 43 $this->break = "\n"; 44 $this->open = ' {'; 45 $this->close = ' }'; 46 $this->tagSeparator = ', '; 47 $this->assignSeparator = ': '; 48 $this->keepSemicolons = true; 49 } 50 51 /** 52 * {@inheritdoc} 53 */ 54 protected function indentStr() 55 { 56 $n = $this->depth - 1; 57 58 return str_repeat($this->indentChar, max($this->indentLevel + $n, 0)); 59 } 60 61 /** 62 * {@inheritdoc} 63 */ 64 protected function blockLines(OutputBlock $block) 65 { 66 $inner = $this->indentStr(); 67 $glue = $this->break . $inner; 68 69 foreach ($block->lines as $index => $line) { 70 if (substr($line, 0, 2) === '/*') { 71 $replacedLine = preg_replace('/\r\n?|\n|\f/', $this->break, $line); 72 assert($replacedLine !== null); 73 $block->lines[$index] = $replacedLine; 74 } 75 } 76 77 $this->write($inner . implode($glue, $block->lines)); 78 } 79 80 /** 81 * {@inheritdoc} 82 */ 83 protected function block(OutputBlock $block) 84 { 85 static $depths; 86 static $downLevel; 87 static $closeBlock; 88 static $previousEmpty; 89 static $previousHasSelector; 90 91 if ($block->type === 'root') { 92 $depths = [ 0 ]; 93 $downLevel = ''; 94 $closeBlock = ''; 95 $this->depth = 0; 96 $previousEmpty = false; 97 $previousHasSelector = false; 98 } 99 100 $isMediaOrDirective = \in_array($block->type, [Type::T_DIRECTIVE, Type::T_MEDIA]); 101 $isSupport = ($block->type === Type::T_DIRECTIVE 102 && $block->selectors && strpos(implode('', $block->selectors), '@supports') !== false); 103 104 while ($block->depth < end($depths) || ($block->depth == 1 && end($depths) == 1)) { 105 array_pop($depths); 106 $this->depth--; 107 108 if ( 109 ! $this->depth && ($block->depth <= 1 || (! $this->indentLevel && $block->type === Type::T_COMMENT)) && 110 (($block->selectors && ! $isMediaOrDirective) || $previousHasSelector) 111 ) { 112 $downLevel = $this->break; 113 } 114 115 if (empty($block->lines) && empty($block->children)) { 116 $previousEmpty = true; 117 } 118 } 119 120 if (empty($block->lines) && empty($block->children)) { 121 return; 122 } 123 124 $this->currentBlock = $block; 125 126 if (! empty($block->lines) || (! empty($block->children) && ($this->depth < 1 || $isSupport))) { 127 if ($block->depth > end($depths)) { 128 if (! $previousEmpty || $this->depth < 1) { 129 $this->depth++; 130 131 $depths[] = $block->depth; 132 } else { 133 // keep the current depth unchanged but take the block depth as a new reference for following blocks 134 array_pop($depths); 135 136 $depths[] = $block->depth; 137 } 138 } 139 } 140 141 $previousEmpty = ($block->type === Type::T_COMMENT); 142 $previousHasSelector = false; 143 144 if (! empty($block->selectors)) { 145 if ($closeBlock) { 146 $this->write($closeBlock); 147 $closeBlock = ''; 148 } 149 150 if ($downLevel) { 151 $this->write($downLevel); 152 $downLevel = ''; 153 } 154 155 $this->blockSelectors($block); 156 157 $this->indentLevel++; 158 } 159 160 if (! empty($block->lines)) { 161 if ($closeBlock) { 162 $this->write($closeBlock); 163 $closeBlock = ''; 164 } 165 166 if ($downLevel) { 167 $this->write($downLevel); 168 $downLevel = ''; 169 } 170 171 $this->blockLines($block); 172 173 $closeBlock = $this->break; 174 } 175 176 if (! empty($block->children)) { 177 if ($this->depth > 0 && ($isMediaOrDirective || ! $this->hasFlatChild($block))) { 178 array_pop($depths); 179 180 $this->depth--; 181 $this->blockChildren($block); 182 $this->depth++; 183 184 $depths[] = $block->depth; 185 } else { 186 $this->blockChildren($block); 187 } 188 } 189 190 // reclear to not be spoiled by children if T_DIRECTIVE 191 if ($block->type === Type::T_DIRECTIVE) { 192 $previousHasSelector = false; 193 } 194 195 if (! empty($block->selectors)) { 196 $this->indentLevel--; 197 198 if (! $this->keepSemicolons) { 199 $this->strippedSemicolon = ''; 200 } 201 202 $this->write($this->close); 203 204 $closeBlock = $this->break; 205 206 if ($this->depth > 1 && ! empty($block->children)) { 207 array_pop($depths); 208 $this->depth--; 209 } 210 211 if (! $isMediaOrDirective) { 212 $previousHasSelector = true; 213 } 214 } 215 216 if ($block->type === 'root') { 217 $this->write($this->break); 218 } 219 } 220 221 /** 222 * Block has flat child 223 * 224 * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block 225 * 226 * @return bool 227 */ 228 private function hasFlatChild($block) 229 { 230 foreach ($block->children as $child) { 231 if (empty($child->selectors)) { 232 return true; 233 } 234 } 235 236 return false; 237 } 238 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body