Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]

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