WP-SCSS - Version 3.0.0

Version Description

  • Updates ScssPHP to version 1.10.0 thanks to fabarea
Download this release

Release Info

Developer Sky Bolt
Plugin Icon wp plugin WP-SCSS
Version 3.0.0
Comparing to
See all releases

Code changes from version 2.4.0 to 3.0.0

readme.md CHANGED
@@ -35,7 +35,9 @@ Compiling comes in two modes:
35
  - Compact - Removes all line breaks, unnecessary whitespace, and single-line comments.
36
  - Crunched - Same as Compressed, but also removes multi-line comments.
37
 
38
- See examples of each in [scssphp's documentation](http://scssphp.github.io/scssphp)
 
 
39
 
40
  #### Source Map Mode
41
 
@@ -59,7 +61,7 @@ Also keep in mind, that if you disable this plugin it can no longer enqueue file
59
 
60
  ## Directions
61
 
62
- _This plugin requires at least php 5.6 to work._
63
 
64
  #### Importing Subfiles
65
 
@@ -110,8 +112,10 @@ This plugin will only work with .scss format.
110
 
111
  ## Changelog
112
 
 
 
113
  - 2.4.0
114
- - Changes the base_compiling_folder to store key not path to directory [shadoath](https://github.com/ConnectThink/WP-SCSS/issues/219)
115
  - This allows deploying from local or staging to production by not saving absolute paths in DB.
116
  - 2.3.5
117
  - Add 'selected' to wp_kses on select() [shadoath](https://github.com/ConnectThink/WP-SCSS/issues/217)
35
  - Compact - Removes all line breaks, unnecessary whitespace, and single-line comments.
36
  - Crunched - Same as Compressed, but also removes multi-line comments.
37
 
38
+ See examples of each in [ScssPHP's documentation](http://scssphp.github.io/scssphp)
39
+
40
+ - Current version of ScssPHP is 1.10.0
41
 
42
  #### Source Map Mode
43
 
61
 
62
  ## Directions
63
 
64
+ _This plugin requires at least php 5.6 to work._ . Tested up to php 7.4
65
 
66
  #### Importing Subfiles
67
 
112
 
113
  ## Changelog
114
 
115
+ - 3.0.0
116
+ - Updates ScssPHP to version [1.10.0](https://github.com/scssphp/scssphp/releases/tag/v1.10.0) thanks to [fabarea](https://github.com/ConnectThink/WP-SCSS/issues/228)
117
  - 2.4.0
118
+ - Changes the base_compiling_folder to store key not path of directory [shadoath](https://github.com/ConnectThink/WP-SCSS/issues/219)
119
  - This allows deploying from local or staging to production by not saving absolute paths in DB.
120
  - 2.3.5
121
  - Add 'selected' to wp_kses on select() [shadoath](https://github.com/ConnectThink/WP-SCSS/issues/217)
readme.txt CHANGED
@@ -3,9 +3,9 @@ Contributors: connectthink, sky-bolt
3
  Tags: sass, scss, css, ScssPhp
4
  Plugin URI: https://github.com/ConnectThink/WP-SCSS
5
  Requires at least: 3.0.1
6
- Tested up to: 5.8
7
  Requires PHP: 5.6
8
- Stable tag: 2.4.0
9
  License: GPLv3 or later
10
  License URI: http://www.gnu.org/copyleft/gpl.html
11
 
@@ -76,6 +76,13 @@ If you are having issues with the plugin, create an issue on [github](https://gi
76
 
77
  == Changelog ==
78
 
 
 
 
 
 
 
 
79
  = 2.3.5 =
80
  - Add 'selected' to wp_kses on select() [shadoath](https://github.com/ConnectThink/WP-SCSS/issues/217)
81
 
3
  Tags: sass, scss, css, ScssPhp
4
  Plugin URI: https://github.com/ConnectThink/WP-SCSS
5
  Requires at least: 3.0.1
6
+ Tested up to: 6.0
7
  Requires PHP: 5.6
8
+ Stable tag: 3.0.0
9
  License: GPLv3 or later
10
  License URI: http://www.gnu.org/copyleft/gpl.html
11
 
76
 
77
  == Changelog ==
78
 
79
+ = 3.0.0 =
80
+ - Updates ScssPHP to version [1.10.0](https://github.com/scssphp/scssphp/releases/tag/v1.10.0) thanks to [fabarea](https://github.com/ConnectThink/WP-SCSS/issues/228)
81
+
82
+ = 2.4.0 =
83
+ - Changes the base_compiling_folder to store key not path to directory [shadoath](https://github.com/ConnectThink/WP-SCSS/issues/219)
84
+ - This allows deploying from local or staging to production by not saving absolute paths in DB.
85
+
86
  = 2.3.5 =
87
  - Add 'selected' to wp_kses on select() [shadoath](https://github.com/ConnectThink/WP-SCSS/issues/217)
88
 
scssphp/bin/pscss CHANGED
@@ -26,7 +26,7 @@ use ScssPhp\ScssPhp\Parser;
26
  use ScssPhp\ScssPhp\Version;
27
 
28
  $style = null;
29
- $loadPaths = null;
30
  $dumpTree = false;
31
  $inputFile = null;
32
  $changeDir = false;
@@ -38,8 +38,8 @@ $embedSourceMap = false;
38
  /**
39
  * Parse argument
40
  *
41
- * @param integer $i
42
- * @param array $options
43
  *
44
  * @return string|null
45
  */
@@ -148,7 +148,7 @@ EOT;
148
  $value = parseArgument($i, array('-I', '--load-path'));
149
 
150
  if (isset($value)) {
151
- $loadPaths = $value;
152
  continue;
153
  }
154
 
@@ -188,7 +188,7 @@ if ($dumpTree) {
188
  $scss = new Compiler();
189
 
190
  if ($loadPaths) {
191
- $scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths));
192
  }
193
 
194
  if ($style) {
26
  use ScssPhp\ScssPhp\Version;
27
 
28
  $style = null;
29
+ $loadPaths = [];
30
  $dumpTree = false;
31
  $inputFile = null;
32
  $changeDir = false;
38
  /**
39
  * Parse argument
40
  *
41
+ * @param int $i
42
+ * @param string[] $options
43
  *
44
  * @return string|null
45
  */
148
  $value = parseArgument($i, array('-I', '--load-path'));
149
 
150
  if (isset($value)) {
151
+ $loadPaths[] = $value;
152
  continue;
153
  }
154
 
188
  $scss = new Compiler();
189
 
190
  if ($loadPaths) {
191
+ $scss->setImportPaths($loadPaths);
192
  }
193
 
194
  if ($style) {
scssphp/composer.json CHANGED
@@ -40,8 +40,9 @@
40
  "sass/sass-spec": "*",
41
  "squizlabs/php_codesniffer": "~3.5",
42
  "symfony/phpunit-bridge": "^5.1",
 
43
  "twbs/bootstrap": "~5.0",
44
- "twbs/bootstrap4": "4.6.0",
45
  "zurb/foundation": "~6.5"
46
  },
47
  "repositories": [
@@ -49,16 +50,34 @@
49
  "type": "package",
50
  "package": {
51
  "name": "sass/sass-spec",
52
- "version": "2021.05.10",
53
  "source": {
54
  "type": "git",
55
  "url": "https://github.com/sass/sass-spec.git",
56
- "reference": "b9bf24a936528f333fb30ee59ca550c6da551c11"
57
  },
58
  "dist": {
59
  "type": "zip",
60
- "url": "https://api.github.com/repos/sass/sass-spec/zipball/b9bf24a936528f333fb30ee59ca550c6da551c11",
61
- "reference": "b9bf24a936528f333fb30ee59ca550c6da551c11",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  "shasum": ""
63
  }
64
  }
@@ -67,16 +86,16 @@
67
  "type": "package",
68
  "package": {
69
  "name": "twbs/bootstrap4",
70
- "version": "v4.6.0",
71
  "source": {
72
  "type": "git",
73
  "url": "https://github.com/twbs/bootstrap.git",
74
- "reference": "6ffb0b48e455430f8a5359ed689ad64c1143fac2"
75
  },
76
  "dist": {
77
  "type": "zip",
78
- "url": "https://api.github.com/repos/twbs/bootstrap/zipball/6ffb0b48e455430f8a5359ed689ad64c1143fac2",
79
- "reference": "6ffb0b48e455430f8a5359ed689ad64c1143fac2",
80
  "shasum": ""
81
  }
82
  }
@@ -84,6 +103,9 @@
84
  ],
85
  "bin": ["bin/pscss"],
86
  "config": {
87
- "sort-packages": true
 
 
 
88
  }
89
  }
40
  "sass/sass-spec": "*",
41
  "squizlabs/php_codesniffer": "~3.5",
42
  "symfony/phpunit-bridge": "^5.1",
43
+ "thoughtbot/bourbon": "^7.0",
44
  "twbs/bootstrap": "~5.0",
45
+ "twbs/bootstrap4": "4.6.1",
46
  "zurb/foundation": "~6.5"
47
  },
48
  "repositories": [
50
  "type": "package",
51
  "package": {
52
  "name": "sass/sass-spec",
53
+ "version": "2021.11.30",
54
  "source": {
55
  "type": "git",
56
  "url": "https://github.com/sass/sass-spec.git",
57
+ "reference": "ee5b460ac84b1ce27b86e22c0252b4296444cf3a"
58
  },
59
  "dist": {
60
  "type": "zip",
61
+ "url": "https://api.github.com/repos/sass/sass-spec/zipball/ee5b460ac84b1ce27b86e22c0252b4296444cf3a",
62
+ "reference": "ee5b460ac84b1ce27b86e22c0252b4296444cf3a",
63
+ "shasum": ""
64
+ }
65
+ }
66
+ },
67
+ {
68
+ "type": "package",
69
+ "package": {
70
+ "name": "thoughtbot/bourbon",
71
+ "version": "v7.0.0",
72
+ "source": {
73
+ "type": "git",
74
+ "url": "https://github.com/thoughtbot/bourbon.git",
75
+ "reference": "fbe338ee6807e7f7aa996d82c8a16f248bb149b3"
76
+ },
77
+ "dist": {
78
+ "type": "zip",
79
+ "url": "https://api.github.com/repos/thoughtbot/bourbon/zipball/fbe338ee6807e7f7aa996d82c8a16f248bb149b3",
80
+ "reference": "fbe338ee6807e7f7aa996d82c8a16f248bb149b3",
81
  "shasum": ""
82
  }
83
  }
86
  "type": "package",
87
  "package": {
88
  "name": "twbs/bootstrap4",
89
+ "version": "v4.6.1",
90
  "source": {
91
  "type": "git",
92
  "url": "https://github.com/twbs/bootstrap.git",
93
+ "reference": "043a03c95a2ad6738f85b65e53b9dbdfb03b8d10"
94
  },
95
  "dist": {
96
  "type": "zip",
97
+ "url": "https://api.github.com/repos/twbs/bootstrap/zipball/043a03c95a2ad6738f85b65e53b9dbdfb03b8d10",
98
+ "reference": "043a03c95a2ad6738f85b65e53b9dbdfb03b8d10",
99
  "shasum": ""
100
  }
101
  }
103
  ],
104
  "bin": ["bin/pscss"],
105
  "config": {
106
+ "sort-packages": true,
107
+ "allow-plugins": {
108
+ "bamarni/composer-bin-plugin": true
109
+ }
110
  }
111
  }
scssphp/src/Base/Range.php CHANGED
@@ -34,8 +34,8 @@ class Range
34
  /**
35
  * Initialize range
36
  *
37
- * @param integer|float $first
38
- * @param integer|float $last
39
  */
40
  public function __construct($first, $last)
41
  {
@@ -46,9 +46,9 @@ class Range
46
  /**
47
  * Test for inclusion in range
48
  *
49
- * @param integer|float $value
50
  *
51
- * @return boolean
52
  */
53
  public function includes($value)
54
  {
34
  /**
35
  * Initialize range
36
  *
37
+ * @param int|float $first
38
+ * @param int|float $last
39
  */
40
  public function __construct($first, $last)
41
  {
46
  /**
47
  * Test for inclusion in range
48
  *
49
+ * @param int|float $value
50
  *
51
+ * @return bool
52
  */
53
  public function includes($value)
54
  {
scssphp/src/Block.php CHANGED
@@ -22,12 +22,12 @@ namespace ScssPhp\ScssPhp;
22
  class Block
23
  {
24
  /**
25
- * @var string
26
  */
27
  public $type;
28
 
29
  /**
30
- * @var \ScssPhp\ScssPhp\Block
31
  */
32
  public $parent;
33
 
@@ -37,17 +37,17 @@ class Block
37
  public $sourceName;
38
 
39
  /**
40
- * @var integer
41
  */
42
  public $sourceIndex;
43
 
44
  /**
45
- * @var integer
46
  */
47
  public $sourceLine;
48
 
49
  /**
50
- * @var integer
51
  */
52
  public $sourceColumn;
53
 
@@ -67,7 +67,7 @@ class Block
67
  public $children;
68
 
69
  /**
70
- * @var \ScssPhp\ScssPhp\Block|null
71
  */
72
  public $selfParent;
73
  }
22
  class Block
23
  {
24
  /**
25
+ * @var string|null
26
  */
27
  public $type;
28
 
29
  /**
30
+ * @var Block|null
31
  */
32
  public $parent;
33
 
37
  public $sourceName;
38
 
39
  /**
40
+ * @var int
41
  */
42
  public $sourceIndex;
43
 
44
  /**
45
+ * @var int
46
  */
47
  public $sourceLine;
48
 
49
  /**
50
+ * @var int
51
  */
52
  public $sourceColumn;
53
 
67
  public $children;
68
 
69
  /**
70
+ * @var Block|null
71
  */
72
  public $selfParent;
73
  }
scssphp/src/Colors.php CHANGED
@@ -204,10 +204,10 @@ class Colors
204
  /**
205
  * Reverse conversion : from RGBA to a color name if possible
206
  *
207
- * @param integer $r
208
- * @param integer $g
209
- * @param integer $b
210
- * @param integer|float $a
211
  *
212
  * @return string|null
213
  */
204
  /**
205
  * Reverse conversion : from RGBA to a color name if possible
206
  *
207
+ * @param int $r
208
+ * @param int $g
209
+ * @param int $b
210
+ * @param int|float $a
211
  *
212
  * @return string|null
213
  */
scssphp/src/Compiler.php CHANGED
@@ -13,6 +13,17 @@
13
  namespace ScssPhp\ScssPhp;
14
 
15
  use ScssPhp\ScssPhp\Base\Range;
 
 
 
 
 
 
 
 
 
 
 
16
  use ScssPhp\ScssPhp\Compiler\CachedResult;
17
  use ScssPhp\ScssPhp\Compiler\Environment;
18
  use ScssPhp\ScssPhp\Exception\CompilerException;
@@ -137,6 +148,7 @@ class Compiler
137
  public static $emptyString = [Type::T_STRING, '"', []];
138
  public static $with = [Type::T_KEYWORD, 'with'];
139
  public static $without = [Type::T_KEYWORD, 'without'];
 
140
 
141
  /**
142
  * @var array<int, string|callable>
@@ -193,6 +205,11 @@ class Compiler
193
  */
194
  protected $sourceMapOptions = [];
195
 
 
 
 
 
 
196
  /**
197
  * @var string|\ScssPhp\ScssPhp\Formatter
198
  */
@@ -221,6 +238,8 @@ class Compiler
221
  protected $storeEnv;
222
  /**
223
  * @var bool|null
 
 
224
  */
225
  protected $charsetSeen;
226
  /**
@@ -463,7 +482,6 @@ class Compiler
463
  $this->env = null;
464
  $this->scope = null;
465
  $this->storeEnv = null;
466
- $this->charsetSeen = null;
467
  $this->shouldEvaluate = null;
468
  $this->ignoreCallStackMessage = false;
469
  $this->parsedFiles = [];
@@ -516,11 +534,9 @@ class Compiler
516
 
517
  $prefix = '';
518
 
519
- if (!$this->charsetSeen) {
520
- if (strlen($out) !== Util::mbStrlen($out)) {
521
- $prefix = '@charset "UTF-8";' . "\n";
522
- $out = $prefix . $out;
523
- }
524
  }
525
 
526
  $sourceMap = null;
@@ -639,7 +655,7 @@ class Compiler
639
  * @param array $target
640
  * @param array $origin
641
  *
642
- * @return boolean
643
  */
644
  protected function isSelfExtend($target, $origin)
645
  {
@@ -848,10 +864,10 @@ class Compiler
848
  /**
849
  * Match extends
850
  *
851
- * @param array $selector
852
- * @param array $out
853
- * @param integer $from
854
- * @param boolean $initial
855
  *
856
  * @return void
857
  */
@@ -984,7 +1000,7 @@ class Compiler
984
  * @param string $part
985
  * @param array $matches
986
  *
987
- * @return boolean
988
  */
989
  protected function isPseudoSelector($part, &$matches)
990
  {
@@ -1046,11 +1062,11 @@ class Compiler
1046
  /**
1047
  * Match extends single
1048
  *
1049
- * @param array $rawSingle
1050
- * @param array $outOrigin
1051
- * @param boolean $initial
1052
  *
1053
- * @return boolean
1054
  */
1055
  protected function matchExtendsSingle($rawSingle, &$outOrigin, $initial = true)
1056
  {
@@ -1265,6 +1281,7 @@ class Compiler
1265
  */
1266
  protected function compileMedia(Block $media)
1267
  {
 
1268
  $this->pushEnv($media);
1269
 
1270
  $mediaQueries = $this->compileMediaQuery($this->multiplyMedia($this->env));
@@ -1342,7 +1359,7 @@ class Compiler
1342
  /**
1343
  * Compile directive
1344
  *
1345
- * @param \ScssPhp\ScssPhp\Block|array $directive
1346
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
1347
  *
1348
  * @return void
@@ -1408,6 +1425,7 @@ class Compiler
1408
  */
1409
  protected function compileAtRoot(Block $block)
1410
  {
 
1411
  $env = $this->pushEnv($block);
1412
  $envs = $this->compactEnv($env);
1413
  list($with, $without) = $this->compileWith(isset($block->with) ? $block->with : null);
@@ -1456,7 +1474,7 @@ class Compiler
1456
  }
1457
 
1458
  /**
1459
- * Filter at-root scope depending of with/without option
1460
  *
1461
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
1462
  * @param array $with
@@ -1556,7 +1574,7 @@ class Compiler
1556
  * Find a selector by the depth node in the scope
1557
  *
1558
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
1559
- * @param integer $depth
1560
  *
1561
  * @return array
1562
  */
@@ -1580,9 +1598,11 @@ class Compiler
1580
  /**
1581
  * Compile @at-root's with: inclusion / without: exclusion into 2 lists uses to filter scope/env later
1582
  *
1583
- * @param array $withCondition
1584
  *
1585
  * @return array
 
 
1586
  */
1587
  protected function compileWith($withCondition)
1588
  {
@@ -1602,9 +1622,10 @@ class Compiler
1602
  }
1603
  }
1604
 
1605
- if ($this->mapHasKey($withCondition, static::$with)) {
 
1606
  $without = []; // cancel the default
1607
- $list = $this->coerceList($this->libMapGet([$withCondition, static::$with]));
1608
 
1609
  foreach ($list[2] as $item) {
1610
  $keyword = $this->compileStringContent($this->coerceString($item));
@@ -1613,9 +1634,10 @@ class Compiler
1613
  }
1614
  }
1615
 
1616
- if ($this->mapHasKey($withCondition, static::$without)) {
 
1617
  $without = []; // cancel the default
1618
- $list = $this->coerceList($this->libMapGet([$withCondition, static::$without]));
1619
 
1620
  foreach ($list[2] as $item) {
1621
  $keyword = $this->compileStringContent($this->coerceString($item));
@@ -1665,7 +1687,7 @@ class Compiler
1665
  * @param array $with
1666
  * @param array $without
1667
  *
1668
- * @return boolean
1669
  */
1670
  protected function isWith($block, $with, $without)
1671
  {
@@ -1675,6 +1697,7 @@ class Compiler
1675
  }
1676
 
1677
  if ($block->type === Type::T_DIRECTIVE) {
 
1678
  if (isset($block->name)) {
1679
  return $this->testWithWithout($this->compileDirectiveName($block->name), $with, $without);
1680
  } elseif (isset($block->selectors) && preg_match(',@(\w+),ims', json_encode($block->selectors), $m)) {
@@ -1710,7 +1733,7 @@ class Compiler
1710
  * @param array $with
1711
  * @param array $without
1712
  *
1713
- * @return boolean
1714
  * true if the block should be kept, false to reject
1715
  */
1716
  protected function testWithWithout($what, $with, $without)
@@ -1765,6 +1788,7 @@ class Compiler
1765
  */
1766
  protected function compileNestedPropertiesBlock(Block $block, OutputBlock $out)
1767
  {
 
1768
  $prefix = $this->compileValue($block->prefix) . '-';
1769
 
1770
  $nested = $this->makeOutputBlock($block->type);
@@ -1783,6 +1807,7 @@ class Compiler
1783
  break;
1784
 
1785
  case Type::T_NESTED_PROPERTY:
 
1786
  array_unshift($child[1]->prefix[2], $prefix);
1787
  break;
1788
  }
@@ -1808,7 +1833,7 @@ class Compiler
1808
 
1809
  // wrap assign children in a block
1810
  // except for @font-face
1811
- if ($block->type !== Type::T_DIRECTIVE || $this->compileDirectiveName($block->name) !== 'font-face') {
1812
  // need wrapping?
1813
  $needWrapping = false;
1814
 
@@ -1897,8 +1922,8 @@ class Compiler
1897
  /**
1898
  * Compile the value of a comment that can have interpolation
1899
  *
1900
- * @param array $value
1901
- * @param boolean $pushEnv
1902
  *
1903
  * @return string
1904
  */
@@ -2215,7 +2240,7 @@ class Compiler
2215
  *
2216
  * @param array $selector
2217
  *
2218
- * @return boolean
2219
  */
2220
  protected function hasSelectorPlaceholder($selector)
2221
  {
@@ -2632,9 +2657,9 @@ class Compiler
2632
  *
2633
  * @param array $rawPath
2634
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
2635
- * @param boolean $once
2636
  *
2637
- * @return boolean
2638
  */
2639
  protected function compileImport($rawPath, OutputBlock $out, $once = false)
2640
  {
@@ -2769,7 +2794,7 @@ class Compiler
2769
  // insert the directive as a comment
2770
  $child = $this->makeOutputBlock(Type::T_COMMENT);
2771
  $child->lines[] = $line;
2772
- $child->sourceName = $this->sourceNames[$this->sourceIndex];
2773
  $child->sourceLine = $this->sourceLine;
2774
  $child->sourceColumn = $this->sourceColumn;
2775
 
@@ -2877,10 +2902,6 @@ class Compiler
2877
  break;
2878
 
2879
  case Type::T_CHARSET:
2880
- if (! $this->charsetSeen) {
2881
- $this->charsetSeen = true;
2882
- $this->appendRootDirective('@charset ' . $this->compileValue($child[1]) . ';', $out);
2883
- }
2884
  break;
2885
 
2886
  case Type::T_CUSTOM_PROPERTY:
@@ -3044,6 +3065,7 @@ class Compiler
3044
  case Type::T_MIXIN:
3045
  case Type::T_FUNCTION:
3046
  list(, $block) = $child;
 
3047
  // the block need to be able to go up to it's parent env to resolve vars
3048
  $block->parentEnv = $this->getStoreEnv();
3049
  $this->set(static::$namespaces[$block->type] . $block->name, $block, true);
@@ -3072,6 +3094,21 @@ class Compiler
3072
  $selectors = $this->multiplySelectors($this->env, $child['selfParent']);
3073
  }
3074
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3075
  $this->pushExtends($result, $selectors, $child);
3076
  }
3077
  }
@@ -3079,6 +3116,7 @@ class Compiler
3079
 
3080
  case Type::T_IF:
3081
  list(, $if) = $child;
 
3082
 
3083
  if ($this->isTruthy($this->reduce($if->cond, true))) {
3084
  return $this->compileChildren($if->children, $out);
@@ -3086,8 +3124,8 @@ class Compiler
3086
 
3087
  foreach ($if->cases as $case) {
3088
  if (
3089
- $case->type === Type::T_ELSE ||
3090
- $case->type === Type::T_ELSEIF && $this->isTruthy($this->reduce($case->cond))
3091
  ) {
3092
  return $this->compileChildren($case->children, $out);
3093
  }
@@ -3096,6 +3134,7 @@ class Compiler
3096
 
3097
  case Type::T_EACH:
3098
  list(, $each) = $child;
 
3099
 
3100
  $list = $this->coerceList($this->reduce($each->list), ',', true);
3101
 
@@ -3130,6 +3169,7 @@ class Compiler
3130
 
3131
  case Type::T_WHILE:
3132
  list(, $while) = $child;
 
3133
 
3134
  while ($this->isTruthy($this->reduce($while->cond, true))) {
3135
  $ret = $this->compileChildren($while->children, $out);
@@ -3142,6 +3182,7 @@ class Compiler
3142
 
3143
  case Type::T_FOR:
3144
  list(, $for) = $child;
 
3145
 
3146
  $startNumber = $this->assertNumber($this->reduce($for->start, true));
3147
  $endNumber = $this->assertNumber($this->reduce($for->end, true));
@@ -3202,6 +3243,8 @@ class Compiler
3202
  throw $this->error("Undefined mixin $name");
3203
  }
3204
 
 
 
3205
  $callingScope = $this->getStoreEnv();
3206
 
3207
  // push scope, apply args
@@ -3374,7 +3417,7 @@ class Compiler
3374
  *
3375
  * @param array|Number $value
3376
  *
3377
- * @return boolean
3378
  */
3379
  public function isTruthy($value)
3380
  {
@@ -3386,7 +3429,7 @@ class Compiler
3386
  *
3387
  * @param string $value
3388
  *
3389
- * @return boolean
3390
  */
3391
  protected function isImmediateRelationshipCombinator($value)
3392
  {
@@ -3398,7 +3441,7 @@ class Compiler
3398
  *
3399
  * @param array $value
3400
  *
3401
- * @return boolean
3402
  */
3403
  protected function shouldEval($value)
3404
  {
@@ -3421,7 +3464,7 @@ class Compiler
3421
  * Reduce value
3422
  *
3423
  * @param array|Number $value
3424
- * @param boolean $inExp
3425
  *
3426
  * @return array|Number
3427
  */
@@ -3812,7 +3855,6 @@ class Compiler
3812
 
3813
  // try to find a native lib function
3814
  $normalizedName = $this->normalizeName($name);
3815
- $libName = null;
3816
 
3817
  if (isset($this->userFunctions[$normalizedName])) {
3818
  // see if we can find a user function
@@ -3821,10 +3863,45 @@ class Compiler
3821
  return [Type::T_FUNCTION_REFERENCE, 'user', $name, $f, $prototype];
3822
  }
3823
 
 
 
 
 
 
 
 
 
3824
  if (($f = $this->getBuiltinFunction($normalizedName)) && \is_callable($f)) {
3825
  $libName = $f[1];
3826
  $prototype = isset(static::$$libName) ? static::$$libName : null;
3827
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3828
  if (\get_class($this) !== __CLASS__ && !isset($this->warnedChildFunctions[$libName])) {
3829
  $r = new \ReflectionMethod($this, $libName);
3830
  $declaringClass = $r->getDeclaringClass()->name;
@@ -3892,6 +3969,10 @@ class Compiler
3892
  unset($value['enclosing']);
3893
  }
3894
 
 
 
 
 
3895
  return $value;
3896
 
3897
  case Type::T_STRING:
@@ -4007,8 +4088,8 @@ class Compiler
4007
  * Boolean and
4008
  *
4009
  * @param array|Number $left
4010
- * @param array|Number $right
4011
- * @param boolean $shouldEval
4012
  *
4013
  * @return array|Number|null
4014
  */
@@ -4036,7 +4117,7 @@ class Compiler
4036
  *
4037
  * @param array|Number $left
4038
  * @param array|Number $right
4039
- * @param boolean $shouldEval
4040
  *
4041
  * @return array|Number|null
4042
  */
@@ -4462,8 +4543,7 @@ class Compiler
4462
  // force double quote as string quote for the output in certain cases
4463
  if (
4464
  $value[1] === "'" &&
4465
- (strpos($content, '"') === false or strpos($content, "'") !== false) &&
4466
- strpbrk($content, '{}\\\'') !== false
4467
  ) {
4468
  $value[1] = '"';
4469
  } elseif (
@@ -4516,6 +4596,8 @@ class Compiler
4516
  }
4517
  }
4518
 
 
 
4519
  $prefix_value = '';
4520
 
4521
  if ($delim !== ' ') {
@@ -4554,7 +4636,7 @@ class Compiler
4554
  $filtered[] = $compiled;
4555
  }
4556
 
4557
- return $pre . substr(implode("$delim", $filtered), \strlen($prefix_value)) . $post;
4558
 
4559
  case Type::T_MAP:
4560
  $keys = $value[1];
@@ -4826,10 +4908,10 @@ class Compiler
4826
  /**
4827
  * Join selectors; looks for & to replace, or append parent before child
4828
  *
4829
- * @param array $parent
4830
- * @param array $child
4831
- * @param boolean $stillHasSelf
4832
- * @param array $selfParentSelectors
4833
 
4834
  * @return array
4835
  */
@@ -4907,6 +4989,8 @@ class Compiler
4907
  return $this->multiplyMedia($env->parent, $childQueries);
4908
  }
4909
 
 
 
4910
  $parentQueries = isset($env->block->queryList)
4911
  ? $env->block->queryList
4912
  : [[[Type::T_MEDIA_VALUE, $env->block->value]]];
@@ -5041,7 +5125,7 @@ class Compiler
5041
  *
5042
  * @param string $name
5043
  * @param mixed $value
5044
- * @param boolean $shadow
5045
  * @param \ScssPhp\ScssPhp\Compiler\Environment $env
5046
  * @param mixed $valueUnreduced
5047
  *
@@ -5147,9 +5231,9 @@ class Compiler
5147
  * @internal
5148
  *
5149
  * @param string $name
5150
- * @param boolean $shouldThrow
5151
  * @param \ScssPhp\ScssPhp\Compiler\Environment $env
5152
- * @param boolean $unreduced
5153
  *
5154
  * @return mixed|null
5155
  */
@@ -5216,7 +5300,7 @@ class Compiler
5216
  * @param string $name
5217
  * @param \ScssPhp\ScssPhp\Compiler\Environment $env
5218
  *
5219
- * @return boolean
5220
  */
5221
  protected function has($name, Environment $env = null)
5222
  {
@@ -5406,7 +5490,7 @@ class Compiler
5406
  *
5407
  * @api
5408
  *
5409
- * @param integer $numberPrecision
5410
  *
5411
  * @return void
5412
  *
@@ -5483,12 +5567,31 @@ class Compiler
5483
  . 'Use source maps instead.', E_USER_DEPRECATED);
5484
  }
5485
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5486
  /**
5487
  * Enable/disable source maps
5488
  *
5489
  * @api
5490
  *
5491
- * @param integer $sourceMap
5492
  *
5493
  * @return void
5494
  *
@@ -5857,7 +5960,7 @@ class Compiler
5857
  }
5858
 
5859
  if (0 === strpos($normalizedPath, $normalizedRootDirectory)) {
5860
- return substr($normalizedPath, \strlen($normalizedRootDirectory));
5861
  }
5862
 
5863
  return $path;
@@ -5890,7 +5993,7 @@ class Compiler
5890
  *
5891
  * @api
5892
  *
5893
- * @param boolean $ignoreErrors
5894
  *
5895
  * @return \ScssPhp\ScssPhp\Compiler
5896
  *
@@ -6029,7 +6132,7 @@ class Compiler
6029
  /**
6030
  * Beautify call stack for output
6031
  *
6032
- * @param boolean $all
6033
  * @param int|null $limit
6034
  *
6035
  * @return string
@@ -6089,8 +6192,8 @@ class Compiler
6089
  /**
6090
  * Call SCSS @function
6091
  *
6092
- * @param Object $func
6093
- * @param array $argValues
6094
  *
6095
  * @return array|Number
6096
  */
@@ -6664,9 +6767,8 @@ class Compiler
6664
  *
6665
  * @param array[] $argDef
6666
  * @param array|null $argValues
6667
- * @param boolean $storeInEnv
6668
- * @param boolean $reduce
6669
- * only used if $storeInEnv = false
6670
  *
6671
  * @return array<string, array|Number>
6672
  *
@@ -6861,14 +6963,18 @@ class Compiler
6861
  }
6862
 
6863
  /**
6864
- * Coerce something to map
6865
  *
6866
- * @param array|Number $item
6867
  *
6868
- * @return array|Number
6869
  */
6870
- protected function coerceMap($item)
6871
  {
 
 
 
 
6872
  if ($item[0] === Type::T_MAP) {
6873
  return $item;
6874
  }
@@ -6880,6 +6986,24 @@ class Compiler
6880
  return static::$emptyMap;
6881
  }
6882
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6883
  return $item;
6884
  }
6885
 
@@ -6888,14 +7012,14 @@ class Compiler
6888
  *
6889
  * @param array|Number $item
6890
  * @param string $delim
6891
- * @param boolean $removeTrailingNull
6892
  *
6893
  * @return array
6894
  */
6895
  protected function coerceList($item, $delim = ',', $removeTrailingNull = false)
6896
  {
6897
  if ($item instanceof Number) {
6898
- return [Type::T_LIST, $delim, [$item]];
6899
  }
6900
 
6901
  if ($item[0] === Type::T_LIST) {
@@ -6916,29 +7040,17 @@ class Compiler
6916
  $key = $keys[$i];
6917
  $value = $values[$i];
6918
 
6919
- switch ($key[0]) {
6920
- case Type::T_LIST:
6921
- case Type::T_MAP:
6922
- case Type::T_STRING:
6923
- case Type::T_NULL:
6924
- break;
6925
-
6926
- default:
6927
- $key = [Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))];
6928
- break;
6929
- }
6930
-
6931
  $list[] = [
6932
  Type::T_LIST,
6933
- '',
6934
  [$key, $value]
6935
  ];
6936
  }
6937
 
6938
- return [Type::T_LIST, ',', $list];
6939
  }
6940
 
6941
- return [Type::T_LIST, $delim, [$item]];
6942
  }
6943
 
6944
  /**
@@ -7079,10 +7191,10 @@ class Compiler
7079
  }
7080
 
7081
  /**
7082
- * @param integer|Number $value
7083
- * @param boolean $isAlpha
7084
  *
7085
- * @return integer|mixed
7086
  */
7087
  protected function compileRGBAValue($value, $isAlpha = false)
7088
  {
@@ -7094,12 +7206,12 @@ class Compiler
7094
  }
7095
 
7096
  /**
7097
- * @param mixed $value
7098
- * @param integer|float $min
7099
- * @param integer|float $max
7100
- * @param boolean $isInt
7101
  *
7102
- * @return integer|mixed
7103
  */
7104
  protected function compileColorPartValue($value, $min, $max, $isInt = true)
7105
  {
@@ -7193,10 +7305,14 @@ class Compiler
7193
  *
7194
  * @param array|Number $value
7195
  *
7196
- * @return integer|float
 
 
7197
  */
7198
  protected function coercePercent($value)
7199
  {
 
 
7200
  if ($value instanceof Number) {
7201
  if ($value->hasUnit('%')) {
7202
  return $value->getDimension() / 100;
@@ -7222,15 +7338,15 @@ class Compiler
7222
  */
7223
  public function assertMap($value, $varName = null)
7224
  {
7225
- $value = $this->coerceMap($value);
7226
 
7227
- if ($value[0] !== Type::T_MAP) {
7228
  $value = $this->compileValue($value);
7229
 
7230
  throw SassScriptException::forArgument("$value is not a map.", $varName);
7231
  }
7232
 
7233
- return $value;
7234
  }
7235
 
7236
  /**
@@ -7327,7 +7443,7 @@ class Compiler
7327
  * @param array|Number $value
7328
  * @param string|null $varName
7329
  *
7330
- * @return integer
7331
  *
7332
  * @throws SassScriptException
7333
  */
@@ -7391,9 +7507,9 @@ class Compiler
7391
  *
7392
  * @internal
7393
  *
7394
- * @param integer $red
7395
- * @param integer $green
7396
- * @param integer $blue
7397
  *
7398
  * @return array
7399
  */
@@ -7423,7 +7539,7 @@ class Compiler
7423
  }
7424
  }
7425
 
7426
- return [Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1];
7427
  }
7428
 
7429
  /**
@@ -7497,9 +7613,9 @@ class Compiler
7497
  *
7498
  * @api
7499
  *
7500
- * @param integer $hue H from 0 to 360
7501
- * @param integer $whiteness W from 0 to 100
7502
- * @param integer $blackness B from 0 to 100
7503
  *
7504
  * @return array
7505
  */
@@ -7529,9 +7645,9 @@ class Compiler
7529
  *
7530
  * @api
7531
  *
7532
- * @param integer $red
7533
- * @param integer $green
7534
- * @param integer $blue
7535
  *
7536
  * @return array
7537
  */
@@ -7659,7 +7775,6 @@ class Compiler
7659
 
7660
  $values = [];
7661
 
7662
-
7663
  foreach ($list[2] as $item) {
7664
  $values[] = $this->normalizeValue($item);
7665
  }
@@ -7704,7 +7819,7 @@ class Compiler
7704
  [$funcName . '(', $color[1], ', ', $color[2], ', ', $color[3], ', ', $alpha, ')']];
7705
  }
7706
  } else {
7707
- $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ')']];
7708
  }
7709
  break;
7710
 
@@ -8005,8 +8120,8 @@ class Compiler
8005
 
8006
  // mix two colors
8007
  protected static $libMix = [
8008
- ['color1', 'color2', 'weight:0.5'],
8009
- ['color-1', 'color-2', 'weight:0.5']
8010
  ];
8011
  protected function libMix($args)
8012
  {
@@ -8014,25 +8129,26 @@ class Compiler
8014
 
8015
  $first = $this->assertColor($first, 'color1');
8016
  $second = $this->assertColor($second, 'color2');
8017
- $weight = $this->coercePercent($this->assertNumber($weight, 'weight'));
8018
 
8019
  $firstAlpha = isset($first[4]) ? $first[4] : 1;
8020
  $secondAlpha = isset($second[4]) ? $second[4] : 1;
8021
 
8022
- $w = $weight * 2 - 1;
8023
- $a = $firstAlpha - $secondAlpha;
8024
 
8025
- $w1 = (($w * $a === -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0;
8026
- $w2 = 1.0 - $w1;
 
8027
 
8028
  $new = [Type::T_COLOR,
8029
- $w1 * $first[1] + $w2 * $second[1],
8030
- $w1 * $first[2] + $w2 * $second[2],
8031
- $w1 * $first[3] + $w2 * $second[3],
8032
  ];
8033
 
8034
  if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
8035
- $new[] = $firstAlpha * $weight + $secondAlpha * (1 - $weight);
8036
  }
8037
 
8038
  return $this->fixColor($new);
@@ -8109,7 +8225,7 @@ class Compiler
8109
  }
8110
  }
8111
 
8112
- $hueValue = $hue->getDimension() % 360;
8113
 
8114
  while ($hueValue < 0) {
8115
  $hueValue += 360;
@@ -8287,10 +8403,23 @@ class Compiler
8287
  }
8288
  */
8289
 
 
 
 
 
 
 
 
8290
  protected function adjustHsl($color, $idx, $amount)
8291
  {
8292
  $hsl = $this->toHSL($color[1], $color[2], $color[3]);
8293
  $hsl[$idx] += $amount;
 
 
 
 
 
 
8294
  $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
8295
 
8296
  if (isset($color[4])) {
@@ -8338,19 +8467,19 @@ class Compiler
8338
  return null;
8339
  }
8340
 
8341
- $color = $this->assertColor($value, 'color');
8342
- $amount = 100 * $this->coercePercent($this->assertNumber($args[1], 'amount'));
8343
 
8344
- return $this->adjustHsl($color, 2, $amount);
8345
  }
8346
 
8347
  protected static $libDesaturate = ['color', 'amount'];
8348
  protected function libDesaturate($args)
8349
  {
8350
  $color = $this->assertColor($args[0], 'color');
8351
- $amount = 100 * $this->coercePercent($this->assertNumber($args[1], 'amount'));
8352
 
8353
- return $this->adjustHsl($color, 2, -$amount);
8354
  }
8355
 
8356
  protected static $libGrayscale = ['color'];
@@ -8371,28 +8500,28 @@ class Compiler
8371
  return $this->adjustHsl($this->assertColor($args[0], 'color'), 1, 180);
8372
  }
8373
 
8374
- protected static $libInvert = ['color', 'weight:1'];
8375
  protected function libInvert($args)
8376
  {
8377
  $value = $args[0];
8378
 
 
 
8379
  if ($value instanceof Number) {
 
 
 
 
8380
  return null;
8381
  }
8382
 
8383
- $weight = $this->coercePercent($this->assertNumber($args[1], 'weight'));
8384
-
8385
  $color = $this->assertColor($value, 'color');
8386
  $inverted = $color;
8387
  $inverted[1] = 255 - $inverted[1];
8388
  $inverted[2] = 255 - $inverted[2];
8389
  $inverted[3] = 255 - $inverted[3];
8390
 
8391
- if ($weight < 1) {
8392
- return $this->libMix([$inverted, $color, new Number($weight, '')]);
8393
- }
8394
-
8395
- return $inverted;
8396
  }
8397
 
8398
  // increases opacity by amount
@@ -8400,9 +8529,9 @@ class Compiler
8400
  protected function libOpacify($args)
8401
  {
8402
  $color = $this->assertColor($args[0], 'color');
8403
- $amount = $this->coercePercent($this->assertNumber($args[1], 'amount'));
8404
 
8405
- $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount;
8406
  $color[4] = min(1, max(0, $color[4]));
8407
 
8408
  return $color;
@@ -8419,9 +8548,9 @@ class Compiler
8419
  protected function libTransparentize($args)
8420
  {
8421
  $color = $this->assertColor($args[0], 'color');
8422
- $amount = $this->coercePercent($this->assertNumber($args[1], 'amount'));
8423
 
8424
- $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount;
8425
  $color[4] = min(1, max(0, $color[4]));
8426
 
8427
  return $color;
@@ -8570,7 +8699,7 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8570
 
8571
  $list = $this->coerceList($args[0]);
8572
 
8573
- if (\count($list[2]) <= 1 && empty($list['enclosing'])) {
8574
  return [Type::T_KEYWORD, 'space'];
8575
  }
8576
 
@@ -8578,6 +8707,10 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8578
  return [Type::T_KEYWORD, 'comma'];
8579
  }
8580
 
 
 
 
 
8581
  return [Type::T_KEYWORD, 'space'];
8582
  }
8583
 
@@ -8617,23 +8750,72 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8617
  return $list;
8618
  }
8619
 
8620
- protected static $libMapGet = ['map', 'key'];
8621
  protected function libMapGet($args)
8622
  {
8623
  $map = $this->assertMap($args[0], 'map');
8624
- $key = $args[1];
 
 
 
 
 
8625
 
8626
- if (! \is_null($key)) {
8627
- $key = $this->compileStringContent($this->coerceString($key));
 
 
8628
 
8629
- for ($i = \count($map[1]) - 1; $i >= 0; $i--) {
8630
- if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
8631
- return $map[2][$i];
8632
- }
8633
  }
 
 
8634
  }
8635
 
8636
- return static::$null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8637
  }
8638
 
8639
  protected static $libMapKeys = ['map'];
@@ -8683,12 +8865,28 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8683
  return $map;
8684
  }
8685
 
8686
- protected static $libMapHasKey = ['map', 'key'];
8687
  protected function libMapHasKey($args)
8688
  {
8689
  $map = $this->assertMap($args[0], 'map');
 
 
 
 
 
 
 
 
 
 
 
 
 
8690
 
8691
- return $this->toBool($this->mapHasKey($map, $args[1]));
 
 
 
8692
  }
8693
 
8694
  /**
@@ -8711,24 +8909,127 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8711
 
8712
  protected static $libMapMerge = [
8713
  ['map1', 'map2'],
8714
- ['map-1', 'map-2']
 
8715
  ];
8716
  protected function libMapMerge($args)
8717
  {
8718
  $map1 = $this->assertMap($args[0], 'map1');
8719
- $map2 = $this->assertMap($args[1], 'map2');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8721
  foreach ($map2[1] as $i2 => $key2) {
8722
- $key = $this->compileStringContent($this->coerceString($key2));
8723
 
8724
- foreach ($map1[1] as $i1 => $key1) {
8725
- if ($key === $this->compileStringContent($this->coerceString($key1))) {
8726
- $map1[2][$i1] = $map2[2][$i2];
8727
- continue 2;
8728
- }
8729
  }
8730
 
8731
- $map1[1][] = $map2[1][$i2];
8732
  $map1[2][] = $map2[2][$i2];
8733
  }
8734
 
@@ -8776,9 +9077,13 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8776
  *
8777
  * @return string
8778
  * @throws CompilerException
 
 
8779
  */
8780
  protected function listSeparatorForJoin($list1, $sep)
8781
  {
 
 
8782
  if (! isset($sep)) {
8783
  return $list1[1];
8784
  }
@@ -8795,14 +9100,40 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8795
  }
8796
  }
8797
 
8798
- protected static $libJoin = ['list1', 'list2', 'separator:null', 'bracketed:auto'];
8799
  protected function libJoin($args)
8800
  {
8801
  list($list1, $list2, $sep, $bracketed) = $args;
8802
 
8803
  $list1 = $this->coerceList($list1, ' ', true);
8804
  $list2 = $this->coerceList($list2, ' ', true);
8805
- $sep = $this->listSeparatorForJoin($list1, $sep);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8806
 
8807
  if ($bracketed === static::$true) {
8808
  $bracketed = true;
@@ -8829,11 +9160,7 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8829
  }
8830
  }
8831
 
8832
- $res = [Type::T_LIST, $sep, array_merge($list1[2], $list2[2])];
8833
-
8834
- if (isset($list1['enclosing'])) {
8835
- $res['enlcosing'] = $list1['enclosing'];
8836
- }
8837
 
8838
  if ($bracketed) {
8839
  $res['enclosing'] = 'bracket';
@@ -8842,14 +9169,35 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8842
  return $res;
8843
  }
8844
 
8845
- protected static $libAppend = ['list', 'val', 'separator:null'];
8846
  protected function libAppend($args)
8847
  {
8848
  list($list1, $value, $sep) = $args;
8849
 
8850
  $list1 = $this->coerceList($list1, ' ', true);
8851
- $sep = $this->listSeparatorForJoin($list1, $sep);
8852
- $res = [Type::T_LIST, $sep, array_merge($list1[2], [$value])];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8853
 
8854
  if (isset($list1['enclosing'])) {
8855
  $res['enclosing'] = $list1['enclosing'];
@@ -8872,7 +9220,7 @@ will be an error in future versions of Sass.\n on line $line of $fname";
8872
  $result = [Type::T_LIST, ',', $lists];
8873
  if (! \is_null($firstList)) {
8874
  foreach ($firstList[2] as $key => $item) {
8875
- $list = [Type::T_LIST, '', [$item]];
8876
 
8877
  foreach ($argLists as $arg) {
8878
  if (isset($arg[2][$key])) {
@@ -9252,6 +9600,8 @@ will be an error in future versions of Sass.\n on line $line of $fname";
9252
  ) {
9253
  $value['enclosing'] = 'forced_' . $value['enclosing'];
9254
  $force_enclosing_display = true;
 
 
9255
  }
9256
 
9257
  foreach ($value[2] as $k => $listelement) {
@@ -9375,7 +9725,7 @@ will be an error in future versions of Sass.\n on line $line of $fname";
9375
  * @param array $super
9376
  * @param array $sub
9377
  *
9378
- * @return boolean
9379
  */
9380
  protected function isSuperSelector($super, $sub)
9381
  {
@@ -9456,7 +9806,7 @@ will be an error in future versions of Sass.\n on line $line of $fname";
9456
  * @param array $superParts
9457
  * @param array $subParts
9458
  *
9459
- * @return boolean
9460
  */
9461
  protected function isSuperPart($superParts, $subParts)
9462
  {
@@ -9523,21 +9873,18 @@ will be an error in future versions of Sass.\n on line $line of $fname";
9523
  // do the trick, happening $lastSelector to $previousSelector
9524
  $appended = [];
9525
 
9526
- foreach ($lastSelectors as $lastSelector) {
9527
- $previous = $previousSelectors;
9528
-
9529
- foreach ($lastSelector as $lastSelectorParts) {
9530
- foreach ($lastSelectorParts as $lastSelectorPart) {
9531
- foreach ($previous as $i => $previousSelector) {
9532
- foreach ($previousSelector as $j => $previousSelectorParts) {
9533
- $previous[$i][$j][] = $lastSelectorPart;
9534
  }
9535
  }
9536
  }
9537
- }
9538
 
9539
- foreach ($previous as $ps) {
9540
- $appended[] = $ps;
9541
  }
9542
  }
9543
 
@@ -9593,10 +9940,10 @@ will be an error in future versions of Sass.\n on line $line of $fname";
9593
  * Extend/replace in selectors
9594
  * used by selector-extend and selector-replace that use the same logic
9595
  *
9596
- * @param array $selectors
9597
- * @param array $extendee
9598
- * @param array $extender
9599
- * @param boolean $replace
9600
  *
9601
  * @return array
9602
  */
13
  namespace ScssPhp\ScssPhp;
14
 
15
  use ScssPhp\ScssPhp\Base\Range;
16
+ use ScssPhp\ScssPhp\Block\AtRootBlock;
17
+ use ScssPhp\ScssPhp\Block\CallableBlock;
18
+ use ScssPhp\ScssPhp\Block\DirectiveBlock;
19
+ use ScssPhp\ScssPhp\Block\EachBlock;
20
+ use ScssPhp\ScssPhp\Block\ElseBlock;
21
+ use ScssPhp\ScssPhp\Block\ElseifBlock;
22
+ use ScssPhp\ScssPhp\Block\ForBlock;
23
+ use ScssPhp\ScssPhp\Block\IfBlock;
24
+ use ScssPhp\ScssPhp\Block\MediaBlock;
25
+ use ScssPhp\ScssPhp\Block\NestedPropertyBlock;
26
+ use ScssPhp\ScssPhp\Block\WhileBlock;
27
  use ScssPhp\ScssPhp\Compiler\CachedResult;
28
  use ScssPhp\ScssPhp\Compiler\Environment;
29
  use ScssPhp\ScssPhp\Exception\CompilerException;
148
  public static $emptyString = [Type::T_STRING, '"', []];
149
  public static $with = [Type::T_KEYWORD, 'with'];
150
  public static $without = [Type::T_KEYWORD, 'without'];
151
+ private static $emptyArgumentList = [Type::T_LIST, '', [], []];
152
 
153
  /**
154
  * @var array<int, string|callable>
205
  */
206
  protected $sourceMapOptions = [];
207
 
208
+ /**
209
+ * @var bool
210
+ */
211
+ private $charset = true;
212
+
213
  /**
214
  * @var string|\ScssPhp\ScssPhp\Formatter
215
  */
238
  protected $storeEnv;
239
  /**
240
  * @var bool|null
241
+ *
242
+ * @deprecated
243
  */
244
  protected $charsetSeen;
245
  /**
482
  $this->env = null;
483
  $this->scope = null;
484
  $this->storeEnv = null;
 
485
  $this->shouldEvaluate = null;
486
  $this->ignoreCallStackMessage = false;
487
  $this->parsedFiles = [];
534
 
535
  $prefix = '';
536
 
537
+ if ($this->charset && strlen($out) !== Util::mbStrlen($out)) {
538
+ $prefix = '@charset "UTF-8";' . "\n";
539
+ $out = $prefix . $out;
 
 
540
  }
541
 
542
  $sourceMap = null;
655
  * @param array $target
656
  * @param array $origin
657
  *
658
+ * @return bool
659
  */
660
  protected function isSelfExtend($target, $origin)
661
  {
864
  /**
865
  * Match extends
866
  *
867
+ * @param array $selector
868
+ * @param array $out
869
+ * @param int $from
870
+ * @param bool $initial
871
  *
872
  * @return void
873
  */
1000
  * @param string $part
1001
  * @param array $matches
1002
  *
1003
+ * @return bool
1004
  */
1005
  protected function isPseudoSelector($part, &$matches)
1006
  {
1062
  /**
1063
  * Match extends single
1064
  *
1065
+ * @param array $rawSingle
1066
+ * @param array $outOrigin
1067
+ * @param bool $initial
1068
  *
1069
+ * @return bool
1070
  */
1071
  protected function matchExtendsSingle($rawSingle, &$outOrigin, $initial = true)
1072
  {
1281
  */
1282
  protected function compileMedia(Block $media)
1283
  {
1284
+ assert($media instanceof MediaBlock);
1285
  $this->pushEnv($media);
1286
 
1287
  $mediaQueries = $this->compileMediaQuery($this->multiplyMedia($this->env));
1359
  /**
1360
  * Compile directive
1361
  *
1362
+ * @param DirectiveBlock|array $directive
1363
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
1364
  *
1365
  * @return void
1425
  */
1426
  protected function compileAtRoot(Block $block)
1427
  {
1428
+ assert($block instanceof AtRootBlock);
1429
  $env = $this->pushEnv($block);
1430
  $envs = $this->compactEnv($env);
1431
  list($with, $without) = $this->compileWith(isset($block->with) ? $block->with : null);
1474
  }
1475
 
1476
  /**
1477
+ * Filter at-root scope depending on with/without option
1478
  *
1479
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
1480
  * @param array $with
1574
  * Find a selector by the depth node in the scope
1575
  *
1576
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
1577
+ * @param int $depth
1578
  *
1579
  * @return array
1580
  */
1598
  /**
1599
  * Compile @at-root's with: inclusion / without: exclusion into 2 lists uses to filter scope/env later
1600
  *
1601
+ * @param array|null $withCondition
1602
  *
1603
  * @return array
1604
+ *
1605
+ * @phpstan-return array{array<string, bool>, array<string, bool>}
1606
  */
1607
  protected function compileWith($withCondition)
1608
  {
1622
  }
1623
  }
1624
 
1625
+ $withConfig = $this->mapGet($withCondition, static::$with);
1626
+ if ($withConfig !== null) {
1627
  $without = []; // cancel the default
1628
+ $list = $this->coerceList($withConfig);
1629
 
1630
  foreach ($list[2] as $item) {
1631
  $keyword = $this->compileStringContent($this->coerceString($item));
1634
  }
1635
  }
1636
 
1637
+ $withoutConfig = $this->mapGet($withCondition, static::$without);
1638
+ if ($withoutConfig !== null) {
1639
  $without = []; // cancel the default
1640
+ $list = $this->coerceList($withoutConfig);
1641
 
1642
  foreach ($list[2] as $item) {
1643
  $keyword = $this->compileStringContent($this->coerceString($item));
1687
  * @param array $with
1688
  * @param array $without
1689
  *
1690
+ * @return bool
1691
  */
1692
  protected function isWith($block, $with, $without)
1693
  {
1697
  }
1698
 
1699
  if ($block->type === Type::T_DIRECTIVE) {
1700
+ assert($block instanceof DirectiveBlock || $block instanceof OutputBlock);
1701
  if (isset($block->name)) {
1702
  return $this->testWithWithout($this->compileDirectiveName($block->name), $with, $without);
1703
  } elseif (isset($block->selectors) && preg_match(',@(\w+),ims', json_encode($block->selectors), $m)) {
1733
  * @param array $with
1734
  * @param array $without
1735
  *
1736
+ * @return bool
1737
  * true if the block should be kept, false to reject
1738
  */
1739
  protected function testWithWithout($what, $with, $without)
1788
  */
1789
  protected function compileNestedPropertiesBlock(Block $block, OutputBlock $out)
1790
  {
1791
+ assert($block instanceof NestedPropertyBlock);
1792
  $prefix = $this->compileValue($block->prefix) . '-';
1793
 
1794
  $nested = $this->makeOutputBlock($block->type);
1807
  break;
1808
 
1809
  case Type::T_NESTED_PROPERTY:
1810
+ assert($child[1] instanceof NestedPropertyBlock);
1811
  array_unshift($child[1]->prefix[2], $prefix);
1812
  break;
1813
  }
1833
 
1834
  // wrap assign children in a block
1835
  // except for @font-face
1836
+ if (!$block instanceof DirectiveBlock || $this->compileDirectiveName($block->name) !== 'font-face') {
1837
  // need wrapping?
1838
  $needWrapping = false;
1839
 
1922
  /**
1923
  * Compile the value of a comment that can have interpolation
1924
  *
1925
+ * @param array $value
1926
+ * @param bool $pushEnv
1927
  *
1928
  * @return string
1929
  */
2240
  *
2241
  * @param array $selector
2242
  *
2243
+ * @return bool
2244
  */
2245
  protected function hasSelectorPlaceholder($selector)
2246
  {
2657
  *
2658
  * @param array $rawPath
2659
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
2660
+ * @param bool $once
2661
  *
2662
+ * @return bool
2663
  */
2664
  protected function compileImport($rawPath, OutputBlock $out, $once = false)
2665
  {
2794
  // insert the directive as a comment
2795
  $child = $this->makeOutputBlock(Type::T_COMMENT);
2796
  $child->lines[] = $line;
2797
+ $child->sourceName = $this->sourceNames[$this->sourceIndex] ?: '(stdin)';
2798
  $child->sourceLine = $this->sourceLine;
2799
  $child->sourceColumn = $this->sourceColumn;
2800
 
2902
  break;
2903
 
2904
  case Type::T_CHARSET:
 
 
 
 
2905
  break;
2906
 
2907
  case Type::T_CUSTOM_PROPERTY:
3065
  case Type::T_MIXIN:
3066
  case Type::T_FUNCTION:
3067
  list(, $block) = $child;
3068
+ assert($block instanceof CallableBlock);
3069
  // the block need to be able to go up to it's parent env to resolve vars
3070
  $block->parentEnv = $this->getStoreEnv();
3071
  $this->set(static::$namespaces[$block->type] . $block->name, $block, true);
3094
  $selectors = $this->multiplySelectors($this->env, $child['selfParent']);
3095
  }
3096
 
3097
+ if (\count($result) > 1) {
3098
+ $replacement = implode(', ', $result);
3099
+ $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]);
3100
+ $line = $this->sourceLine;
3101
+
3102
+ $message = <<<EOL
3103
+ on line $line of $fname:
3104
+ Compound selectors may no longer be extended.
3105
+ Consider `@extend $replacement` instead.
3106
+ See http://bit.ly/ExtendCompound for details.
3107
+ EOL;
3108
+
3109
+ $this->logger->warn($message);
3110
+ }
3111
+
3112
  $this->pushExtends($result, $selectors, $child);
3113
  }
3114
  }
3116
 
3117
  case Type::T_IF:
3118
  list(, $if) = $child;
3119
+ assert($if instanceof IfBlock);
3120
 
3121
  if ($this->isTruthy($this->reduce($if->cond, true))) {
3122
  return $this->compileChildren($if->children, $out);
3124
 
3125
  foreach ($if->cases as $case) {
3126
  if (
3127
+ $case instanceof ElseBlock ||
3128
+ $case instanceof ElseifBlock && $this->isTruthy($this->reduce($case->cond))
3129
  ) {
3130
  return $this->compileChildren($case->children, $out);
3131
  }
3134
 
3135
  case Type::T_EACH:
3136
  list(, $each) = $child;
3137
+ assert($each instanceof EachBlock);
3138
 
3139
  $list = $this->coerceList($this->reduce($each->list), ',', true);
3140
 
3169
 
3170
  case Type::T_WHILE:
3171
  list(, $while) = $child;
3172
+ assert($while instanceof WhileBlock);
3173
 
3174
  while ($this->isTruthy($this->reduce($while->cond, true))) {
3175
  $ret = $this->compileChildren($while->children, $out);
3182
 
3183
  case Type::T_FOR:
3184
  list(, $for) = $child;
3185
+ assert($for instanceof ForBlock);
3186
 
3187
  $startNumber = $this->assertNumber($this->reduce($for->start, true));
3188
  $endNumber = $this->assertNumber($this->reduce($for->end, true));
3243
  throw $this->error("Undefined mixin $name");
3244
  }
3245
 
3246
+ assert($mixin instanceof CallableBlock);
3247
+
3248
  $callingScope = $this->getStoreEnv();
3249
 
3250
  // push scope, apply args
3417
  *
3418
  * @param array|Number $value
3419
  *
3420
+ * @return bool
3421
  */
3422
  public function isTruthy($value)
3423
  {
3429
  *
3430
  * @param string $value
3431
  *
3432
+ * @return bool
3433
  */
3434
  protected function isImmediateRelationshipCombinator($value)
3435
  {
3441
  *
3442
  * @param array $value
3443
  *
3444
+ * @return bool
3445
  */
3446
  protected function shouldEval($value)
3447
  {
3464
  * Reduce value
3465
  *
3466
  * @param array|Number $value
3467
+ * @param bool $inExp
3468
  *
3469
  * @return array|Number
3470
  */
3855
 
3856
  // try to find a native lib function
3857
  $normalizedName = $this->normalizeName($name);
 
3858
 
3859
  if (isset($this->userFunctions[$normalizedName])) {
3860
  // see if we can find a user function
3863
  return [Type::T_FUNCTION_REFERENCE, 'user', $name, $f, $prototype];
3864
  }
3865
 
3866
+ $lowercasedName = strtolower($normalizedName);
3867
+
3868
+ // Special functions overriding a CSS function are case-insensitive. We normalize them as lowercase
3869
+ // to avoid the deprecation warning about the wrong case being used.
3870
+ if ($lowercasedName === 'min' || $lowercasedName === 'max') {
3871
+ $normalizedName = $lowercasedName;
3872
+ }
3873
+
3874
  if (($f = $this->getBuiltinFunction($normalizedName)) && \is_callable($f)) {
3875
  $libName = $f[1];
3876
  $prototype = isset(static::$$libName) ? static::$$libName : null;
3877
 
3878
+ // All core functions have a prototype defined. Not finding the
3879
+ // prototype can mean 2 things:
3880
+ // - the function comes from a child class (deprecated just after)
3881
+ // - the function was found with a different case, which relates to calling the
3882
+ // wrong Sass function due to our camelCase usage (`fade-in()` vs `fadein()`),
3883
+ // because PHP method names are case-insensitive while property names are
3884
+ // case-sensitive.
3885
+ if ($prototype === null || strtolower($normalizedName) !== $normalizedName) {
3886
+ $r = new \ReflectionMethod($this, $libName);
3887
+ $actualLibName = $r->name;
3888
+
3889
+ if ($actualLibName !== $libName || strtolower($normalizedName) !== $normalizedName) {
3890
+ $kebabCaseName = preg_replace('~(?<=\\w)([A-Z])~', '-$1', substr($actualLibName, 3));
3891
+ assert($kebabCaseName !== null);
3892
+ $originalName = strtolower($kebabCaseName);
3893
+ $warning = "Calling built-in functions with a non-standard name is deprecated since Scssphp 1.8.0 and will not work anymore in 2.0 (they will be treated as CSS function calls instead).\nUse \"$originalName\" instead of \"$name\".";
3894
+ @trigger_error($warning, E_USER_DEPRECATED);
3895
+ $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]);
3896
+ $line = $this->sourceLine;
3897
+ Warn::deprecation("$warning\n on line $line of $fname");
3898
+
3899
+ // Use the actual function definition
3900
+ $prototype = isset(static::$$actualLibName) ? static::$$actualLibName : null;
3901
+ $f[1] = $libName = $actualLibName;
3902
+ }
3903
+ }
3904
+
3905
  if (\get_class($this) !== __CLASS__ && !isset($this->warnedChildFunctions[$libName])) {
3906
  $r = new \ReflectionMethod($this, $libName);
3907
  $declaringClass = $r->getDeclaringClass()->name;
3969
  unset($value['enclosing']);
3970
  }
3971
 
3972
+ if ($value[1] === '' && count($value[2]) > 1) {
3973
+ $value[1] = ' ';
3974
+ }
3975
+
3976
  return $value;
3977
 
3978
  case Type::T_STRING:
4088
  * Boolean and
4089
  *
4090
  * @param array|Number $left
4091
+ * @param array|Number $right
4092
+ * @param bool $shouldEval
4093
  *
4094
  * @return array|Number|null
4095
  */
4117
  *
4118
  * @param array|Number $left
4119
  * @param array|Number $right
4120
+ * @param bool $shouldEval
4121
  *
4122
  * @return array|Number|null
4123
  */
4543
  // force double quote as string quote for the output in certain cases
4544
  if (
4545
  $value[1] === "'" &&
4546
+ (strpos($content, '"') === false or strpos($content, "'") !== false)
 
4547
  ) {
4548
  $value[1] = '"';
4549
  } elseif (
4596
  }
4597
  }
4598
 
4599
+ $separator = $delim === '/' ? ' /' : $delim;
4600
+
4601
  $prefix_value = '';
4602
 
4603
  if ($delim !== ' ') {
4636
  $filtered[] = $compiled;
4637
  }
4638
 
4639
+ return $pre . substr(implode($separator, $filtered), \strlen($prefix_value)) . $post;
4640
 
4641
  case Type::T_MAP:
4642
  $keys = $value[1];
4908
  /**
4909
  * Join selectors; looks for & to replace, or append parent before child
4910
  *
4911
+ * @param array $parent
4912
+ * @param array $child
4913
+ * @param bool $stillHasSelf
4914
+ * @param array $selfParentSelectors
4915
 
4916
  * @return array
4917
  */
4989
  return $this->multiplyMedia($env->parent, $childQueries);
4990
  }
4991
 
4992
+ assert($env->block instanceof MediaBlock);
4993
+
4994
  $parentQueries = isset($env->block->queryList)
4995
  ? $env->block->queryList
4996
  : [[[Type::T_MEDIA_VALUE, $env->block->value]]];
5125
  *
5126
  * @param string $name
5127
  * @param mixed $value
5128
+ * @param bool $shadow
5129
  * @param \ScssPhp\ScssPhp\Compiler\Environment $env
5130
  * @param mixed $valueUnreduced
5131
  *
5231
  * @internal
5232
  *
5233
  * @param string $name
5234
+ * @param bool $shouldThrow
5235
  * @param \ScssPhp\ScssPhp\Compiler\Environment $env
5236
+ * @param bool $unreduced
5237
  *
5238
  * @return mixed|null
5239
  */
5300
  * @param string $name
5301
  * @param \ScssPhp\ScssPhp\Compiler\Environment $env
5302
  *
5303
+ * @return bool
5304
  */
5305
  protected function has($name, Environment $env = null)
5306
  {
5490
  *
5491
  * @api
5492
  *
5493
+ * @param int $numberPrecision
5494
  *
5495
  * @return void
5496
  *
5567
  . 'Use source maps instead.', E_USER_DEPRECATED);
5568
  }
5569
 
5570
+ /**
5571
+ * Configures the handling of non-ASCII outputs.
5572
+ *
5573
+ * If $charset is `true`, this will include a `@charset` declaration or a
5574
+ * UTF-8 [byte-order mark][] if the stylesheet contains any non-ASCII
5575
+ * characters. Otherwise, it will never include a `@charset` declaration or a
5576
+ * byte-order mark.
5577
+ *
5578
+ * [byte-order mark]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8
5579
+ *
5580
+ * @param bool $charset
5581
+ *
5582
+ * @return void
5583
+ */
5584
+ public function setCharset($charset)
5585
+ {
5586
+ $this->charset = $charset;
5587
+ }
5588
+
5589
  /**
5590
  * Enable/disable source maps
5591
  *
5592
  * @api
5593
  *
5594
+ * @param int $sourceMap
5595
  *
5596
  * @return void
5597
  *
5960
  }
5961
 
5962
  if (0 === strpos($normalizedPath, $normalizedRootDirectory)) {
5963
+ return substr($path, \strlen($normalizedRootDirectory));
5964
  }
5965
 
5966
  return $path;
5993
  *
5994
  * @api
5995
  *
5996
+ * @param bool $ignoreErrors
5997
  *
5998
  * @return \ScssPhp\ScssPhp\Compiler
5999
  *
6132
  /**
6133
  * Beautify call stack for output
6134
  *
6135
+ * @param bool $all
6136
  * @param int|null $limit
6137
  *
6138
  * @return string
6192
  /**
6193
  * Call SCSS @function
6194
  *
6195
+ * @param CallableBlock|null $func
6196
+ * @param array $argValues
6197
  *
6198
  * @return array|Number
6199
  */
6767
  *
6768
  * @param array[] $argDef
6769
  * @param array|null $argValues
6770
+ * @param bool $storeInEnv
6771
+ * @param bool $reduce only used if $storeInEnv = false
 
6772
  *
6773
  * @return array<string, array|Number>
6774
  *
6963
  }
6964
 
6965
  /**
6966
+ * Tries to convert an item to a Sass map
6967
  *
6968
+ * @param Number|array $item
6969
  *
6970
+ * @return array|null
6971
  */
6972
+ private function tryMap($item)
6973
  {
6974
+ if ($item instanceof Number) {
6975
+ return null;
6976
+ }
6977
+
6978
  if ($item[0] === Type::T_MAP) {
6979
  return $item;
6980
  }
6986
  return static::$emptyMap;
6987
  }
6988
 
6989
+ return null;
6990
+ }
6991
+
6992
+ /**
6993
+ * Coerce something to map
6994
+ *
6995
+ * @param array|Number $item
6996
+ *
6997
+ * @return array|Number
6998
+ */
6999
+ protected function coerceMap($item)
7000
+ {
7001
+ $map = $this->tryMap($item);
7002
+
7003
+ if ($map !== null) {
7004
+ return $map;
7005
+ }
7006
+
7007
  return $item;
7008
  }
7009
 
7012
  *
7013
  * @param array|Number $item
7014
  * @param string $delim
7015
+ * @param bool $removeTrailingNull
7016
  *
7017
  * @return array
7018
  */
7019
  protected function coerceList($item, $delim = ',', $removeTrailingNull = false)
7020
  {
7021
  if ($item instanceof Number) {
7022
+ return [Type::T_LIST, '', [$item]];
7023
  }
7024
 
7025
  if ($item[0] === Type::T_LIST) {
7040
  $key = $keys[$i];
7041
  $value = $values[$i];
7042
 
 
 
 
 
 
 
 
 
 
 
 
 
7043
  $list[] = [
7044
  Type::T_LIST,
7045
+ ' ',
7046
  [$key, $value]
7047
  ];
7048
  }
7049
 
7050
+ return [Type::T_LIST, $list ? ',' : '', $list];
7051
  }
7052
 
7053
+ return [Type::T_LIST, '', [$item]];
7054
  }
7055
 
7056
  /**
7191
  }
7192
 
7193
  /**
7194
+ * @param int|Number $value
7195
+ * @param bool $isAlpha
7196
  *
7197
+ * @return int|mixed
7198
  */
7199
  protected function compileRGBAValue($value, $isAlpha = false)
7200
  {
7206
  }
7207
 
7208
  /**
7209
+ * @param mixed $value
7210
+ * @param int|float $min
7211
+ * @param int|float $max
7212
+ * @param bool $isInt
7213
  *
7214
+ * @return int|mixed
7215
  */
7216
  protected function compileColorPartValue($value, $min, $max, $isInt = true)
7217
  {
7305
  *
7306
  * @param array|Number $value
7307
  *
7308
+ * @return int|float
7309
+ *
7310
+ * @deprecated
7311
  */
7312
  protected function coercePercent($value)
7313
  {
7314
+ @trigger_error(sprintf('"%s" is deprecated since 1.7.0.', __METHOD__), E_USER_DEPRECATED);
7315
+
7316
  if ($value instanceof Number) {
7317
  if ($value->hasUnit('%')) {
7318
  return $value->getDimension() / 100;
7338
  */
7339
  public function assertMap($value, $varName = null)
7340
  {
7341
+ $map = $this->tryMap($value);
7342
 
7343
+ if ($map === null) {
7344
  $value = $this->compileValue($value);
7345
 
7346
  throw SassScriptException::forArgument("$value is not a map.", $varName);
7347
  }
7348
 
7349
+ return $map;
7350
  }
7351
 
7352
  /**
7443
  * @param array|Number $value
7444
  * @param string|null $varName
7445
  *
7446
+ * @return int
7447
  *
7448
  * @throws SassScriptException
7449
  */
7507
  *
7508
  * @internal
7509
  *
7510
+ * @param int $red
7511
+ * @param int $green
7512
+ * @param int $blue
7513
  *
7514
  * @return array
7515
  */
7539
  }
7540
  }
7541
 
7542
+ return [Type::T_HSL, fmod($h + 360, 360), $s * 100, $l / 5.1];
7543
  }
7544
 
7545
  /**
7613
  *
7614
  * @api
7615
  *
7616
+ * @param int $hue H from 0 to 360
7617
+ * @param int $whiteness W from 0 to 100
7618
+ * @param int $blackness B from 0 to 100
7619
  *
7620
  * @return array
7621
  */
7645
  *
7646
  * @api
7647
  *
7648
+ * @param int $red
7649
+ * @param int $green
7650
+ * @param int $blue
7651
  *
7652
  * @return array
7653
  */
7775
 
7776
  $values = [];
7777
 
 
7778
  foreach ($list[2] as $item) {
7779
  $values[] = $this->normalizeValue($item);
7780
  }
7819
  [$funcName . '(', $color[1], ', ', $color[2], ', ', $color[3], ', ', $alpha, ')']];
7820
  }
7821
  } else {
7822
+ $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ')']];
7823
  }
7824
  break;
7825
 
8120
 
8121
  // mix two colors
8122
  protected static $libMix = [
8123
+ ['color1', 'color2', 'weight:50%'],
8124
+ ['color-1', 'color-2', 'weight:50%']
8125
  ];
8126
  protected function libMix($args)
8127
  {
8129
 
8130
  $first = $this->assertColor($first, 'color1');
8131
  $second = $this->assertColor($second, 'color2');
8132
+ $weightScale = $this->assertNumber($weight, 'weight')->valueInRange(0, 100, 'weight') / 100;
8133
 
8134
  $firstAlpha = isset($first[4]) ? $first[4] : 1;
8135
  $secondAlpha = isset($second[4]) ? $second[4] : 1;
8136
 
8137
+ $normalizedWeight = $weightScale * 2 - 1;
8138
+ $alphaDistance = $firstAlpha - $secondAlpha;
8139
 
8140
+ $combinedWeight = $normalizedWeight * $alphaDistance == -1 ? $normalizedWeight : ($normalizedWeight + $alphaDistance) / (1 + $normalizedWeight * $alphaDistance);
8141
+ $weight1 = ($combinedWeight + 1) / 2.0;
8142
+ $weight2 = 1.0 - $weight1;
8143
 
8144
  $new = [Type::T_COLOR,
8145
+ $weight1 * $first[1] + $weight2 * $second[1],
8146
+ $weight1 * $first[2] + $weight2 * $second[2],
8147
+ $weight1 * $first[3] + $weight2 * $second[3],
8148
  ];
8149
 
8150
  if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
8151
+ $new[] = $firstAlpha * $weightScale + $secondAlpha * (1 - $weightScale);
8152
  }
8153
 
8154
  return $this->fixColor($new);
8225
  }
8226
  }
8227
 
8228
+ $hueValue = fmod($hue->getDimension(), 360);
8229
 
8230
  while ($hueValue < 0) {
8231
  $hueValue += 360;
8403
  }
8404
  */
8405
 
8406
+ /**
8407
+ * @param array $color
8408
+ * @param int $idx
8409
+ * @param int|float $amount
8410
+ *
8411
+ * @return array
8412
+ */
8413
  protected function adjustHsl($color, $idx, $amount)
8414
  {
8415
  $hsl = $this->toHSL($color[1], $color[2], $color[3]);
8416
  $hsl[$idx] += $amount;
8417
+
8418
+ if ($idx !== 1) {
8419
+ // Clamp the saturation and lightness
8420
+ $hsl[$idx] = min(max(0, $hsl[$idx]), 100);
8421
+ }
8422
+
8423
  $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
8424
 
8425
  if (isset($color[4])) {
8467
  return null;
8468
  }
8469
 
8470
+ $color = $this->assertColor($args[0], 'color');
8471
+ $amount = $this->assertNumber($args[1], 'amount');
8472
 
8473
+ return $this->adjustHsl($color, 2, $amount->valueInRange(0, 100, 'amount'));
8474
  }
8475
 
8476
  protected static $libDesaturate = ['color', 'amount'];
8477
  protected function libDesaturate($args)
8478
  {
8479
  $color = $this->assertColor($args[0], 'color');
8480
+ $amount = $this->assertNumber($args[1], 'amount');
8481
 
8482
+ return $this->adjustHsl($color, 2, -$amount->valueInRange(0, 100, 'amount'));
8483
  }
8484
 
8485
  protected static $libGrayscale = ['color'];
8500
  return $this->adjustHsl($this->assertColor($args[0], 'color'), 1, 180);
8501
  }
8502
 
8503
+ protected static $libInvert = ['color', 'weight:100%'];
8504
  protected function libInvert($args)
8505
  {
8506
  $value = $args[0];
8507
 
8508
+ $weight = $this->assertNumber($args[1], 'weight');
8509
+
8510
  if ($value instanceof Number) {
8511
+ if ($weight->getDimension() != 100 || !$weight->hasUnit('%')) {
8512
+ throw new SassScriptException('Only one argument may be passed to the plain-CSS invert() function.');
8513
+ }
8514
+
8515
  return null;
8516
  }
8517
 
 
 
8518
  $color = $this->assertColor($value, 'color');
8519
  $inverted = $color;
8520
  $inverted[1] = 255 - $inverted[1];
8521
  $inverted[2] = 255 - $inverted[2];
8522
  $inverted[3] = 255 - $inverted[3];
8523
 
8524
+ return $this->libMix([$inverted, $color, $weight]);
 
 
 
 
8525
  }
8526
 
8527
  // increases opacity by amount
8529
  protected function libOpacify($args)
8530
  {
8531
  $color = $this->assertColor($args[0], 'color');
8532
+ $amount = $this->assertNumber($args[1], 'amount');
8533
 
8534
+ $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount->valueInRange(0, 1, 'amount');
8535
  $color[4] = min(1, max(0, $color[4]));
8536
 
8537
  return $color;
8548
  protected function libTransparentize($args)
8549
  {
8550
  $color = $this->assertColor($args[0], 'color');
8551
+ $amount = $this->assertNumber($args[1], 'amount');
8552
 
8553
+ $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount->valueInRange(0, 1, 'amount');
8554
  $color[4] = min(1, max(0, $color[4]));
8555
 
8556
  return $color;
8699
 
8700
  $list = $this->coerceList($args[0]);
8701
 
8702
+ if ($list[1] === '' && \count($list[2]) <= 1 && empty($list['enclosing'])) {
8703
  return [Type::T_KEYWORD, 'space'];
8704
  }
8705
 
8707
  return [Type::T_KEYWORD, 'comma'];
8708
  }
8709
 
8710
+ if ($list[1] === '/') {
8711
+ return [Type::T_KEYWORD, 'slash'];
8712
+ }
8713
+
8714
  return [Type::T_KEYWORD, 'space'];
8715
  }
8716
 
8750
  return $list;
8751
  }
8752
 
8753
+ protected static $libMapGet = ['map', 'key', 'keys...'];
8754
  protected function libMapGet($args)
8755
  {
8756
  $map = $this->assertMap($args[0], 'map');
8757
+ if (!isset($args[2])) {
8758
+ // BC layer for usages of the function from PHP code rather than from the Sass function
8759
+ $args[2] = self::$emptyArgumentList;
8760
+ }
8761
+ $keys = array_merge([$args[1]], $args[2][2]);
8762
+ $value = static::$null;
8763
 
8764
+ foreach ($keys as $key) {
8765
+ if (!\is_array($map) || $map[0] !== Type::T_MAP) {
8766
+ return static::$null;
8767
+ }
8768
 
8769
+ $map = $this->mapGet($map, $key);
8770
+
8771
+ if ($map === null) {
8772
+ return static::$null;
8773
  }
8774
+
8775
+ $value = $map;
8776
  }
8777
 
8778
+ return $value;
8779
+ }
8780
+
8781
+ /**
8782
+ * Gets the value corresponding to that key in the map
8783
+ *
8784
+ * @param array $map
8785
+ * @param Number|array $key
8786
+ *
8787
+ * @return Number|array|null
8788
+ */
8789
+ private function mapGet(array $map, $key)
8790
+ {
8791
+ $index = $this->mapGetEntryIndex($map, $key);
8792
+
8793
+ if ($index !== null) {
8794
+ return $map[2][$index];
8795
+ }
8796
+
8797
+ return null;
8798
+ }
8799
+
8800
+ /**
8801
+ * Gets the index corresponding to that key in the map entries
8802
+ *
8803
+ * @param array $map
8804
+ * @param Number|array $key
8805
+ *
8806
+ * @return int|null
8807
+ */
8808
+ private function mapGetEntryIndex(array $map, $key)
8809
+ {
8810
+ $key = $this->compileStringContent($this->coerceString($key));
8811
+
8812
+ for ($i = \count($map[1]) - 1; $i >= 0; $i--) {
8813
+ if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
8814
+ return $i;
8815
+ }
8816
+ }
8817
+
8818
+ return null;
8819
  }
8820
 
8821
  protected static $libMapKeys = ['map'];
8865
  return $map;
8866
  }
8867
 
8868
+ protected static $libMapHasKey = ['map', 'key', 'keys...'];
8869
  protected function libMapHasKey($args)
8870
  {
8871
  $map = $this->assertMap($args[0], 'map');
8872
+ if (!isset($args[2])) {
8873
+ // BC layer for usages of the function from PHP code rather than from the Sass function
8874
+ $args[2] = self::$emptyArgumentList;
8875
+ }
8876
+ $keys = array_merge([$args[1]], $args[2][2]);
8877
+ $lastKey = array_pop($keys);
8878
+
8879
+ foreach ($keys as $key) {
8880
+ $value = $this->mapGet($map, $key);
8881
+
8882
+ if ($value === null || $value instanceof Number || $value[0] !== Type::T_MAP) {
8883
+ return self::$false;
8884
+ }
8885
 
8886
+ $map = $value;
8887
+ }
8888
+
8889
+ return $this->toBool($this->mapHasKey($map, $lastKey));
8890
  }
8891
 
8892
  /**
8909
 
8910
  protected static $libMapMerge = [
8911
  ['map1', 'map2'],
8912
+ ['map-1', 'map-2'],
8913
+ ['map1', 'args...']
8914
  ];
8915
  protected function libMapMerge($args)
8916
  {
8917
  $map1 = $this->assertMap($args[0], 'map1');
8918
+ $map2 = $args[1];
8919
+ $keys = [];
8920
+ if ($map2[0] === Type::T_LIST && isset($map2[3]) && \is_array($map2[3])) {
8921
+ // This is an argument list for the variadic signature
8922
+ if (\count($map2[2]) === 0) {
8923
+ throw new SassScriptException('Expected $args to contain a key.');
8924
+ }
8925
+ if (\count($map2[2]) === 1) {
8926
+ throw new SassScriptException('Expected $args to contain a value.');
8927
+ }
8928
+ $keys = $map2[2];
8929
+ $map2 = array_pop($keys);
8930
+ }
8931
+ $map2 = $this->assertMap($map2, 'map2');
8932
+
8933
+ return $this->modifyMap($map1, $keys, function ($oldValue) use ($map2) {
8934
+ $nestedMap = $this->tryMap($oldValue);
8935
 
8936
+ if ($nestedMap === null) {
8937
+ return $map2;
8938
+ }
8939
+
8940
+ return $this->mergeMaps($nestedMap, $map2);
8941
+ });
8942
+ }
8943
+
8944
+ /**
8945
+ * @param array $map
8946
+ * @param array $keys
8947
+ * @param callable $modify
8948
+ * @param bool $addNesting
8949
+ *
8950
+ * @return Number|array
8951
+ *
8952
+ * @phpstan-param array<Number|array> $keys
8953
+ * @phpstan-param callable(Number|array): (Number|array) $modify
8954
+ */
8955
+ private function modifyMap(array $map, array $keys, callable $modify, $addNesting = true)
8956
+ {
8957
+ if ($keys === []) {
8958
+ return $modify($map);
8959
+ }
8960
+
8961
+ return $this->modifyNestedMap($map, $keys, $modify, $addNesting);
8962
+ }
8963
+
8964
+ /**
8965
+ * @param array $map
8966
+ * @param array $keys
8967
+ * @param callable $modify
8968
+ * @param bool $addNesting
8969
+ *
8970
+ * @return array
8971
+ *
8972
+ * @phpstan-param non-empty-array<Number|array> $keys
8973
+ * @phpstan-param callable(Number|array): (Number|array) $modify
8974
+ */
8975
+ private function modifyNestedMap(array $map, array $keys, callable $modify, $addNesting)
8976
+ {
8977
+ $key = array_shift($keys);
8978
+
8979
+ $nestedValueIndex = $this->mapGetEntryIndex($map, $key);
8980
+
8981
+ if ($keys === []) {
8982
+ if ($nestedValueIndex !== null) {
8983
+ $map[2][$nestedValueIndex] = $modify($map[2][$nestedValueIndex]);
8984
+ } else {
8985
+ $map[1][] = $key;
8986
+ $map[2][] = $modify(self::$null);
8987
+ }
8988
+
8989
+ return $map;
8990
+ }
8991
+
8992
+ $nestedMap = $nestedValueIndex !== null ? $this->tryMap($map[2][$nestedValueIndex]) : null;
8993
+
8994
+ if ($nestedMap === null && !$addNesting) {
8995
+ return $map;
8996
+ }
8997
+
8998
+ if ($nestedMap === null) {
8999
+ $nestedMap = self::$emptyMap;
9000
+ }
9001
+
9002
+ $newNestedMap = $this->modifyNestedMap($nestedMap, $keys, $modify, $addNesting);
9003
+
9004
+ if ($nestedValueIndex !== null) {
9005
+ $map[2][$nestedValueIndex] = $newNestedMap;
9006
+ } else {
9007
+ $map[1][] = $key;
9008
+ $map[2][] = $newNestedMap;
9009
+ }
9010
+
9011
+ return $map;
9012
+ }
9013
+
9014
+ /**
9015
+ * Merges 2 Sass maps together
9016
+ *
9017
+ * @param array $map1
9018
+ * @param array $map2
9019
+ *
9020
+ * @return array
9021
+ */
9022
+ private function mergeMaps(array $map1, array $map2)
9023
+ {
9024
  foreach ($map2[1] as $i2 => $key2) {
9025
+ $map1EntryIndex = $this->mapGetEntryIndex($map1, $key2);
9026
 
9027
+ if ($map1EntryIndex !== null) {
9028
+ $map1[2][$map1EntryIndex] = $map2[2][$i2];
9029
+ continue;
 
 
9030
  }
9031
 
9032
+ $map1[1][] = $key2;
9033
  $map1[2][] = $map2[2][$i2];
9034
  }
9035
 
9077
  *
9078
  * @return string
9079
  * @throws CompilerException
9080
+ *
9081
+ * @deprecated
9082
  */
9083
  protected function listSeparatorForJoin($list1, $sep)
9084
  {
9085
+ @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED);
9086
+
9087
  if (! isset($sep)) {
9088
  return $list1[1];
9089
  }
9100
  }
9101
  }
9102
 
9103
+ protected static $libJoin = ['list1', 'list2', 'separator:auto', 'bracketed:auto'];
9104
  protected function libJoin($args)
9105
  {
9106
  list($list1, $list2, $sep, $bracketed) = $args;
9107
 
9108
  $list1 = $this->coerceList($list1, ' ', true);
9109
  $list2 = $this->coerceList($list2, ' ', true);
9110
+
9111
+ switch ($this->compileStringContent($this->assertString($sep, 'separator'))) {
9112
+ case 'comma':
9113
+ $separator = ',';
9114
+ break;
9115
+
9116
+ case 'space':
9117
+ $separator = ' ';
9118
+ break;
9119
+
9120
+ case 'slash':
9121
+ $separator = '/';
9122
+ break;
9123
+
9124
+ case 'auto':
9125
+ if ($list1[1] !== '' || count($list1[2]) > 1 || !empty($list1['enclosing']) && $list1['enclosing'] !== 'parent') {
9126
+ $separator = $list1[1] ?: ' ';
9127
+ } elseif ($list2[1] !== '' || count($list2[2]) > 1 || !empty($list2['enclosing']) && $list2['enclosing'] !== 'parent') {
9128
+ $separator = $list2[1] ?: ' ';
9129
+ } else {
9130
+ $separator = ' ';
9131
+ }
9132
+ break;
9133
+
9134
+ default:
9135
+ throw SassScriptException::forArgument('Must be "space", "comma", "slash", or "auto".', 'separator');
9136
+ }
9137
 
9138
  if ($bracketed === static::$true) {
9139
  $bracketed = true;
9160
  }
9161
  }
9162
 
9163
+ $res = [Type::T_LIST, $separator, array_merge($list1[2], $list2[2])];
 
 
 
 
9164
 
9165
  if ($bracketed) {
9166
  $res['enclosing'] = 'bracket';
9169
  return $res;
9170
  }
9171
 
9172
+ protected static $libAppend = ['list', 'val', 'separator:auto'];
9173
  protected function libAppend($args)
9174
  {
9175
  list($list1, $value, $sep) = $args;
9176
 
9177
  $list1 = $this->coerceList($list1, ' ', true);
9178
+
9179
+ switch ($this->compileStringContent($this->assertString($sep, 'separator'))) {
9180
+ case 'comma':
9181
+ $separator = ',';
9182
+ break;
9183
+
9184
+ case 'space':
9185
+ $separator = ' ';
9186
+ break;
9187
+
9188
+ case 'slash':
9189
+ $separator = '/';
9190
+ break;
9191
+
9192
+ case 'auto':
9193
+ $separator = $list1[1] === '' && \count($list1[2]) <= 1 && (empty($list1['enclosing']) || $list1['enclosing'] === 'parent') ? ' ' : $list1[1];
9194
+ break;
9195
+
9196
+ default:
9197
+ throw SassScriptException::forArgument('Must be "space", "comma", "slash", or "auto".', 'separator');
9198
+ }
9199
+
9200
+ $res = [Type::T_LIST, $separator, array_merge($list1[2], [$value])];
9201
 
9202
  if (isset($list1['enclosing'])) {
9203
  $res['enclosing'] = $list1['enclosing'];
9220
  $result = [Type::T_LIST, ',', $lists];
9221
  if (! \is_null($firstList)) {
9222
  foreach ($firstList[2] as $key => $item) {
9223
+ $list = [Type::T_LIST, ' ', [$item]];
9224
 
9225
  foreach ($argLists as $arg) {
9226
  if (isset($arg[2][$key])) {
9600
  ) {
9601
  $value['enclosing'] = 'forced_' . $value['enclosing'];
9602
  $force_enclosing_display = true;
9603
+ } elseif (! \count($value[2])) {
9604
+ $value['enclosing'] = 'forced_parent';
9605
  }
9606
 
9607
  foreach ($value[2] as $k => $listelement) {
9725
  * @param array $super
9726
  * @param array $sub
9727
  *
9728
+ * @return bool
9729
  */
9730
  protected function isSuperSelector($super, $sub)
9731
  {
9806
  * @param array $superParts
9807
  * @param array $subParts
9808
  *
9809
+ * @return bool
9810
  */
9811
  protected function isSuperPart($superParts, $subParts)
9812
  {
9873
  // do the trick, happening $lastSelector to $previousSelector
9874
  $appended = [];
9875
 
9876
+ foreach ($previousSelectors as $previousSelector) {
9877
+ foreach ($lastSelectors as $lastSelector) {
9878
+ $previous = $previousSelector;
9879
+ foreach ($previousSelector as $j => $previousSelectorParts) {
9880
+ foreach ($lastSelector as $lastSelectorParts) {
9881
+ foreach ($lastSelectorParts as $lastSelectorPart) {
9882
+ $previous[$j][] = $lastSelectorPart;
 
9883
  }
9884
  }
9885
  }
 
9886
 
9887
+ $appended[] = $previous;
 
9888
  }
9889
  }
9890
 
9940
  * Extend/replace in selectors
9941
  * used by selector-extend and selector-replace that use the same logic
9942
  *
9943
+ * @param array $selectors
9944
+ * @param array $extendee
9945
+ * @param array $extender
9946
+ * @param bool $replace
9947
  *
9948
  * @return array
9949
  */
scssphp/src/Compiler/Environment.php CHANGED
@@ -31,6 +31,26 @@ class Environment
31
  */
32
  public $parent;
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  /**
35
  * @var array
36
  */
@@ -42,7 +62,7 @@ class Environment
42
  public $storeUnreduced;
43
 
44
  /**
45
- * @var integer
46
  */
47
  public $depth;
48
  }
31
  */
32
  public $parent;
33
 
34
+ /**
35
+ * @var Environment|null
36
+ */
37
+ public $declarationScopeParent;
38
+
39
+ /**
40
+ * @var Environment|null
41
+ */
42
+ public $parentStore;
43
+
44
+ /**
45
+ * @var array|null
46
+ */
47
+ public $selectors;
48
+
49
+ /**
50
+ * @var string|null
51
+ */
52
+ public $marker;
53
+
54
  /**
55
  * @var array
56
  */
62
  public $storeUnreduced;
63
 
64
  /**
65
+ * @var int
66
  */
67
  public $depth;
68
  }
scssphp/src/Formatter.php CHANGED
@@ -25,7 +25,7 @@ use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator;
25
  abstract class Formatter
26
  {
27
  /**
28
- * @var integer
29
  */
30
  public $indentLevel;
31
 
@@ -60,7 +60,7 @@ abstract class Formatter
60
  public $assignSeparator;
61
 
62
  /**
63
- * @var boolean
64
  */
65
  public $keepSemicolons;
66
 
@@ -70,12 +70,12 @@ abstract class Formatter
70
  protected $currentBlock;
71
 
72
  /**
73
- * @var integer
74
  */
75
  protected $currentLine;
76
 
77
  /**
78
- * @var integer
79
  */
80
  protected $currentColumn;
81
 
@@ -239,7 +239,7 @@ abstract class Formatter
239
  *
240
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
241
  *
242
- * @return boolean
243
  */
244
  protected function testEmptyChildren($block)
245
  {
25
  abstract class Formatter
26
  {
27
  /**
28
+ * @var int
29
  */
30
  public $indentLevel;
31
 
60
  public $assignSeparator;
61
 
62
  /**
63
+ * @var bool
64
  */
65
  public $keepSemicolons;
66
 
70
  protected $currentBlock;
71
 
72
  /**
73
+ * @var int
74
  */
75
  protected $currentLine;
76
 
77
  /**
78
+ * @var int
79
  */
80
  protected $currentColumn;
81
 
239
  *
240
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
241
  *
242
+ * @return bool
243
  */
244
  protected function testEmptyChildren($block)
245
  {
scssphp/src/Formatter/Compressed.php CHANGED
@@ -50,8 +50,6 @@ class Compressed extends Formatter
50
  foreach ($block->lines as $index => $line) {
51
  if (substr($line, 0, 2) === '/*' && substr($line, 2, 1) !== '!') {
52
  unset($block->lines[$index]);
53
- } elseif (substr($line, 0, 3) === '/*!') {
54
- $block->lines[$index] = '/*' . substr($line, 3);
55
  }
56
  }
57
 
50
  foreach ($block->lines as $index => $line) {
51
  if (substr($line, 0, 2) === '/*' && substr($line, 2, 1) !== '!') {
52
  unset($block->lines[$index]);
 
 
53
  }
54
  }
55
 
scssphp/src/Formatter/Nested.php CHANGED
@@ -27,7 +27,7 @@ use ScssPhp\ScssPhp\Type;
27
  class Nested extends Formatter
28
  {
29
  /**
30
- * @var integer
31
  */
32
  private $depth;
33
 
@@ -221,7 +221,7 @@ class Nested extends Formatter
221
  *
222
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
223
  *
224
- * @return boolean
225
  */
226
  private function hasFlatChild($block)
227
  {
27
  class Nested extends Formatter
28
  {
29
  /**
30
+ * @var int
31
  */
32
  private $depth;
33
 
221
  *
222
  * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
223
  *
224
+ * @return bool
225
  */
226
  private function hasFlatChild($block)
227
  {
scssphp/src/Formatter/OutputBlock.php CHANGED
@@ -27,7 +27,7 @@ class OutputBlock
27
  public $type;
28
 
29
  /**
30
- * @var integer
31
  */
32
  public $depth;
33
 
@@ -57,12 +57,12 @@ class OutputBlock
57
  public $sourceName;
58
 
59
  /**
60
- * @var integer|null
61
  */
62
  public $sourceLine;
63
 
64
  /**
65
- * @var integer|null
66
  */
67
  public $sourceColumn;
68
  }
27
  public $type;
28
 
29
  /**
30
+ * @var int
31
  */
32
  public $depth;
33
 
57
  public $sourceName;
58
 
59
  /**
60
+ * @var int|null
61
  */
62
  public $sourceLine;
63
 
64
  /**
65
+ * @var int|null
66
  */
67
  public $sourceColumn;
68
  }
scssphp/src/Node.php CHANGED
@@ -27,7 +27,7 @@ abstract class Node
27
  public $type;
28
 
29
  /**
30
- * @var integer
31
  */
32
  public $sourceIndex;
33
 
27
  public $type;
28
 
29
  /**
30
+ * @var int
31
  */
32
  public $sourceIndex;
33
 
scssphp/src/Node/Number.php CHANGED
@@ -38,7 +38,7 @@ class Number extends Node implements \ArrayAccess
38
  const PRECISION = 10;
39
 
40
  /**
41
- * @var integer
42
  * @deprecated use {Number::PRECISION} instead to read the precision. Configuring it is not supported anymore.
43
  */
44
  public static $precision = self::PRECISION;
@@ -81,7 +81,7 @@ class Number extends Node implements \ArrayAccess
81
  ];
82
 
83
  /**
84
- * @var integer|float
85
  */
86
  private $dimension;
87
 
@@ -100,7 +100,7 @@ class Number extends Node implements \ArrayAccess
100
  /**
101
  * Initialize number
102
  *
103
- * @param integer|float $dimension
104
  * @param string[]|string $numeratorUnits
105
  * @param string[] $denominatorUnits
106
  *
@@ -147,8 +147,9 @@ class Number extends Node implements \ArrayAccess
147
  }
148
 
149
  /**
150
- * {@inheritdoc}
151
  */
 
152
  public function offsetExists($offset)
153
  {
154
  if ($offset === -3) {
@@ -172,8 +173,9 @@ class Number extends Node implements \ArrayAccess
172
  }
173
 
174
  /**
175
- * {@inheritdoc}
176
  */
 
177
  public function offsetGet($offset)
178
  {
179
  switch ($offset) {
@@ -198,16 +200,18 @@ class Number extends Node implements \ArrayAccess
198
  }
199
 
200
  /**
201
- * {@inheritdoc}
202
  */
 
203
  public function offsetSet($offset, $value)
204
  {
205
  throw new \BadMethodCallException('Number is immutable');
206
  }
207
 
208
  /**
209
- * {@inheritdoc}
210
  */
 
211
  public function offsetUnset($offset)
212
  {
213
  throw new \BadMethodCallException('Number is immutable');
@@ -216,7 +220,7 @@ class Number extends Node implements \ArrayAccess
216
  /**
217
  * Returns true if the number is unitless
218
  *
219
- * @return boolean
220
  */
221
  public function unitless()
222
  {
38
  const PRECISION = 10;
39
 
40
  /**
41
+ * @var int
42
  * @deprecated use {Number::PRECISION} instead to read the precision. Configuring it is not supported anymore.
43
  */
44
  public static $precision = self::PRECISION;
81
  ];
82
 
83
  /**
84
+ * @var int|float
85
  */
86
  private $dimension;
87
 
100
  /**
101
  * Initialize number
102
  *
103
+ * @param int|float $dimension
104
  * @param string[]|string $numeratorUnits
105
  * @param string[] $denominatorUnits
106
  *
147
  }
148
 
149
  /**
150
+ * @return bool
151
  */
152
+ #[\ReturnTypeWillChange]
153
  public function offsetExists($offset)
154
  {
155
  if ($offset === -3) {
173
  }
174
 
175
  /**
176
+ * @return mixed
177
  */
178
+ #[\ReturnTypeWillChange]
179
  public function offsetGet($offset)
180
  {
181
  switch ($offset) {
200
  }
201
 
202
  /**
203
+ * @return void
204
  */
205
+ #[\ReturnTypeWillChange]
206
  public function offsetSet($offset, $value)
207
  {
208
  throw new \BadMethodCallException('Number is immutable');
209
  }
210
 
211
  /**
212
+ * @return void
213
  */
214
+ #[\ReturnTypeWillChange]
215
  public function offsetUnset($offset)
216
  {
217
  throw new \BadMethodCallException('Number is immutable');
220
  /**
221
  * Returns true if the number is unitless
222
  *
223
+ * @return bool
224
  */
225
  public function unitless()
226
  {
scssphp/src/Parser.php CHANGED
@@ -12,6 +12,18 @@
12
 
13
  namespace ScssPhp\ScssPhp;
14
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  use ScssPhp\ScssPhp\Exception\ParserException;
16
  use ScssPhp\ScssPhp\Logger\LoggerInterface;
17
  use ScssPhp\ScssPhp\Logger\QuietLogger;
@@ -125,7 +137,7 @@ class Parser
125
  * @api
126
  *
127
  * @param string|null $sourceName
128
- * @param integer $sourceIndex
129
  * @param string|null $encoding
130
  * @param Cache|null $cache
131
  * @param bool $cssOnly
@@ -305,7 +317,7 @@ class Parser
305
  * @param string $buffer
306
  * @param string|array $out
307
  *
308
- * @return boolean
309
  */
310
  public function parseValue($buffer, &$out)
311
  {
@@ -334,7 +346,7 @@ class Parser
334
  * @param string|array $out
335
  * @param bool $shouldValidate
336
  *
337
- * @return boolean
338
  */
339
  public function parseSelector($buffer, &$out, $shouldValidate = true)
340
  {
@@ -371,7 +383,7 @@ class Parser
371
  * @param string $buffer
372
  * @param string|array $out
373
  *
374
- * @return boolean
375
  */
376
  public function parseMediaQueryList($buffer, &$out)
377
  {
@@ -428,7 +440,7 @@ class Parser
428
  * position into $s. Then if a chain fails, use $this->seek($s) to
429
  * go back where we started.
430
  *
431
- * @return boolean
432
  */
433
  protected function parseChunk()
434
  {
@@ -447,7 +459,8 @@ class Parser
447
  ) {
448
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
449
 
450
- $atRoot = $this->pushSpecialBlock(Type::T_AT_ROOT, $s);
 
451
  $atRoot->selector = $selector;
452
  $atRoot->with = $with;
453
 
@@ -461,7 +474,8 @@ class Parser
461
  $this->mediaQueryList($mediaQueryList) &&
462
  $this->matchChar('{', false)
463
  ) {
464
- $media = $this->pushSpecialBlock(Type::T_MEDIA, $s);
 
465
  $media->queryList = $mediaQueryList[2];
466
 
467
  return true;
@@ -477,7 +491,8 @@ class Parser
477
  ) {
478
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
479
 
480
- $mixin = $this->pushSpecialBlock(Type::T_MIXIN, $s);
 
481
  $mixin->name = $mixinName;
482
  $mixin->args = $args;
483
 
@@ -509,7 +524,8 @@ class Parser
509
  ];
510
 
511
  if (! empty($hasBlock)) {
512
- $include = $this->pushSpecialBlock(Type::T_INCLUDE, $s);
 
513
  $include->child = $child;
514
  } else {
515
  $this->append($child, $s);
@@ -599,7 +615,8 @@ class Parser
599
  ) {
600
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
601
 
602
- $func = $this->pushSpecialBlock(Type::T_FUNCTION, $s);
 
603
  $func->name = $fnName;
604
  $func->args = $args;
605
 
@@ -631,7 +648,8 @@ class Parser
631
  ) {
632
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
633
 
634
- $each = $this->pushSpecialBlock(Type::T_EACH, $s);
 
635
 
636
  foreach ($varNames[2] as $varName) {
637
  $each->vars[] = $varName[1];
@@ -660,7 +678,8 @@ class Parser
660
  $cond = reset($cond[2]);
661
  }
662
 
663
- $while = $this->pushSpecialBlock(Type::T_WHILE, $s);
 
664
  $while->cond = $cond;
665
 
666
  return true;
@@ -680,7 +699,8 @@ class Parser
680
  ) {
681
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
682
 
683
- $for = $this->pushSpecialBlock(Type::T_FOR, $s);
 
684
  $for->var = $varName[1];
685
  $for->start = $start;
686
  $for->end = $end;
@@ -697,7 +717,8 @@ class Parser
697
  ) {
698
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
699
 
700
- $if = $this->pushSpecialBlock(Type::T_IF, $s);
 
701
 
702
  while (
703
  $cond[0] === Type::T_LIST &&
@@ -776,20 +797,21 @@ class Parser
776
 
777
  if (isset($last) && $last[0] === Type::T_IF) {
778
  list(, $if) = $last;
 
779
 
780
  if ($this->literal('@else', 5)) {
781
  if ($this->matchChar('{', false)) {
782
- $else = $this->pushSpecialBlock(Type::T_ELSE, $s);
783
  } elseif (
784
  $this->literal('if', 2) &&
785
  $this->functionCallArgumentsList($cond, false, '{', false)
786
  ) {
787
- $else = $this->pushSpecialBlock(Type::T_ELSEIF, $s);
788
  $else->cond = $cond;
789
  }
790
 
791
  if (isset($else)) {
792
- $else->dontAppend = true;
793
  $if->cases[] = $else;
794
 
795
  return true;
@@ -827,7 +849,8 @@ class Parser
827
  ($t1 = $this->supportsQuery($supportQuery)) &&
828
  ($t2 = $this->matchChar('{', false))
829
  ) {
830
- $directive = $this->pushSpecialBlock(Type::T_DIRECTIVE, $s);
 
831
  $directive->name = 'supports';
832
  $directive->value = $supportQuery;
833
 
@@ -848,11 +871,12 @@ class Parser
848
  $dirName = [Type::T_STRING, '', $dirName];
849
  }
850
  if ($dirName === 'media') {
851
- $directive = $this->pushSpecialBlock(Type::T_MEDIA, $s);
852
  } else {
853
- $directive = $this->pushSpecialBlock(Type::T_DIRECTIVE, $s);
854
  $directive->name = $dirName;
855
  }
 
856
 
857
  if (isset($dirValue)) {
858
  ! $this->cssOnly || ($dirValue = $this->assertPlainCssValid($dirValue));
@@ -1028,7 +1052,8 @@ class Parser
1028
  if ($this->matchChar('{', false)) {
1029
  ! $this->cssOnly || $this->assertPlainCssValid(false);
1030
 
1031
- $propBlock = $this->pushSpecialBlock(Type::T_NESTED_PROPERTY, $s);
 
1032
  $propBlock->prefix = $name;
1033
  $propBlock->hasValue = $foundSomething;
1034
 
@@ -1054,12 +1079,13 @@ class Parser
1054
  }
1055
  }
1056
 
1057
- if (isset($block->type) && $block->type === Type::T_INCLUDE) {
1058
  $include = $block->child;
 
1059
  unset($block->child);
1060
  $include[3] = $block;
1061
  $this->append($include, $s);
1062
- } elseif (empty($block->dontAppend)) {
1063
  $type = isset($block->type) ? $block->type : Type::T_BLOCK;
1064
  $this->append([$type, $block], $s);
1065
  }
@@ -1088,20 +1114,34 @@ class Parser
1088
  * Push block onto parse tree
1089
  *
1090
  * @param array|null $selectors
1091
- * @param integer $pos
1092
  *
1093
  * @return Block
1094
  */
1095
  protected function pushBlock($selectors, $pos = 0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1096
  {
1097
  list($line, $column) = $this->getSourcePosition($pos);
1098
 
1099
- $b = new Block();
1100
  $b->sourceName = $this->sourceName;
1101
  $b->sourceLine = $line;
1102
  $b->sourceColumn = $column;
1103
  $b->sourceIndex = $this->sourceIndex;
1104
- $b->selectors = $selectors;
1105
  $b->comments = [];
1106
  $b->parent = $this->env;
1107
 
@@ -1126,15 +1166,15 @@ class Parser
1126
  $this->append(null);
1127
  }
1128
  }
1129
-
1130
- return $b;
1131
  }
1132
 
1133
  /**
1134
  * Push special (named) block onto parse tree
1135
  *
 
 
1136
  * @param string $type
1137
- * @param integer $pos
1138
  *
1139
  * @return Block
1140
  */
@@ -1183,11 +1223,11 @@ class Parser
1183
  /**
1184
  * Peek input stream
1185
  *
1186
- * @param string $regex
1187
- * @param array $out
1188
- * @param integer $from
1189
  *
1190
- * @return integer
1191
  */
1192
  protected function peek($regex, &$out, $from = null)
1193
  {
@@ -1204,7 +1244,7 @@ class Parser
1204
  /**
1205
  * Seek to position in input stream (or return current position in input stream)
1206
  *
1207
- * @param integer $where
1208
  */
1209
  protected function seek($where)
1210
  {
@@ -1215,7 +1255,8 @@ class Parser
1215
  * Assert a parsed part is plain CSS Valid
1216
  *
1217
  * @param array|false $parsed
1218
- * @param int $startPos
 
1219
  * @throws ParserException
1220
  */
1221
  protected function assertPlainCssValid($parsed, $startPos = null)
@@ -1243,7 +1284,10 @@ class Parser
1243
 
1244
  /**
1245
  * Check a parsed element is plain CSS Valid
 
1246
  * @param array $parsed
 
 
1247
  * @return bool|array
1248
  */
1249
  protected function isPlainCssValidElement($parsed, $allowExpression = false)
@@ -1423,7 +1467,7 @@ class Parser
1423
  * @param array $m Matches (passed by reference)
1424
  * @param string $delim Delimiter
1425
  *
1426
- * @return boolean True if match; false otherwise
1427
  */
1428
  protected function matchString(&$m, $delim)
1429
  {
@@ -1459,11 +1503,11 @@ class Parser
1459
  /**
1460
  * Try to match something on head of buffer
1461
  *
1462
- * @param string $regex
1463
- * @param array $out
1464
- * @param boolean $eatWhitespace
1465
  *
1466
- * @return boolean
1467
  */
1468
  protected function match($regex, &$out, $eatWhitespace = null)
1469
  {
@@ -1489,10 +1533,10 @@ class Parser
1489
  /**
1490
  * Match a single string
1491
  *
1492
- * @param string $char
1493
- * @param boolean $eatWhitespace
1494
  *
1495
- * @return boolean
1496
  */
1497
  protected function matchChar($char, $eatWhitespace = null)
1498
  {
@@ -1516,11 +1560,11 @@ class Parser
1516
  /**
1517
  * Match literal string
1518
  *
1519
- * @param string $what
1520
- * @param integer $len
1521
- * @param boolean $eatWhitespace
1522
  *
1523
- * @return boolean
1524
  */
1525
  protected function literal($what, $len, $eatWhitespace = null)
1526
  {
@@ -1544,7 +1588,7 @@ class Parser
1544
  /**
1545
  * Match some whitespace
1546
  *
1547
- * @return boolean
1548
  */
1549
  protected function whitespace()
1550
  {
@@ -1580,7 +1624,9 @@ class Parser
1580
  } else {
1581
  list($line, $column) = $this->getSourcePosition($this->count);
1582
  $file = $this->sourceName;
1583
- $this->logger->warn("Unterminated interpolations in multiline comments are deprecated and will be removed in ScssPhp 2.0, in \"$file\", line $line, column $column.", true);
 
 
1584
  $comment[] = substr($this->buffer, $this->count, 2);
1585
 
1586
  $this->count += 2;
@@ -1641,7 +1687,7 @@ class Parser
1641
  * Append statement to current block
1642
  *
1643
  * @param array|null $statement
1644
- * @param integer $pos
1645
  */
1646
  protected function append($statement, $pos = null)
1647
  {
@@ -1686,7 +1732,7 @@ class Parser
1686
  *
1687
  * @param array $out
1688
  *
1689
- * @return boolean
1690
  */
1691
  protected function mediaQueryList(&$out)
1692
  {
@@ -1698,7 +1744,7 @@ class Parser
1698
  *
1699
  * @param array $out
1700
  *
1701
- * @return boolean
1702
  */
1703
  protected function mediaQuery(&$out)
1704
  {
@@ -1752,7 +1798,7 @@ class Parser
1752
  *
1753
  * @param array $out
1754
  *
1755
- * @return boolean
1756
  */
1757
  protected function supportsQuery(&$out)
1758
  {
@@ -1885,7 +1931,7 @@ class Parser
1885
  *
1886
  * @param array $out
1887
  *
1888
- * @return boolean
1889
  */
1890
  protected function mediaExpression(&$out)
1891
  {
@@ -1918,7 +1964,7 @@ class Parser
1918
  *
1919
  * @param array $out
1920
  *
1921
- * @return boolean
1922
  */
1923
  protected function argValues(&$out)
1924
  {
@@ -1943,7 +1989,7 @@ class Parser
1943
  *
1944
  * @param array $out
1945
  *
1946
- * @return boolean
1947
  */
1948
  protected function argValue(&$out)
1949
  {
@@ -2023,10 +2069,10 @@ class Parser
2023
  /**
2024
  * Parse directive value list that considers $vars as keyword
2025
  *
2026
- * @param array $out
2027
- * @param boolean|string $endChar
2028
  *
2029
- * @return boolean
2030
  */
2031
  protected function directiveValue(&$out, $endChar = false)
2032
  {
@@ -2087,7 +2133,7 @@ class Parser
2087
  *
2088
  * @param array $out
2089
  *
2090
- * @return boolean
2091
  */
2092
  protected function valueList(&$out)
2093
  {
@@ -2103,10 +2149,11 @@ class Parser
2103
  * Parse a function call, where externals () are part of the call
2104
  * and not of the value list
2105
  *
2106
- * @param $out
2107
- * @param bool $mandatoryEnclos
2108
  * @param null|string $charAfter
2109
- * @param null|bool $eatWhiteSp
 
2110
  * @return bool
2111
  */
2112
  protected function functionCallArgumentsList(&$out, $mandatoryEnclos = true, $charAfter = null, $eatWhiteSp = null)
@@ -2143,7 +2190,7 @@ class Parser
2143
  *
2144
  * @param array $out
2145
  *
2146
- * @return boolean
2147
  */
2148
  protected function spaceList(&$out)
2149
  {
@@ -2153,12 +2200,12 @@ class Parser
2153
  /**
2154
  * Parse generic list
2155
  *
2156
- * @param array $out
2157
- * @param string $parseItem The name of the method used to parse items
2158
- * @param string $delim
2159
- * @param boolean $flatten
2160
  *
2161
- * @return boolean
2162
  */
2163
  protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
2164
  {
@@ -2254,11 +2301,11 @@ class Parser
2254
  /**
2255
  * Parse expression
2256
  *
2257
- * @param array $out
2258
- * @param boolean $listOnly
2259
- * @param boolean $lookForExp
2260
  *
2261
- * @return boolean
2262
  */
2263
  protected function expression(&$out, $listOnly = false, $lookForExp = true)
2264
  {
@@ -2320,11 +2367,11 @@ class Parser
2320
  * Parse expression specifically checking for lists in parenthesis or brackets
2321
  *
2322
  * @param array $out
2323
- * @param integer $s
2324
  * @param string $closingParen
2325
  * @param array $allowedTypes
2326
  *
2327
- * @return boolean
2328
  */
2329
  protected function enclosedExpression(&$out, $s, $closingParen = ')', $allowedTypes = [Type::T_LIST, Type::T_MAP])
2330
  {
@@ -2379,8 +2426,8 @@ class Parser
2379
  /**
2380
  * Parse left-hand side of subexpression
2381
  *
2382
- * @param array $lhs
2383
- * @param integer $minP
2384
  *
2385
  * @return array
2386
  */
@@ -2415,10 +2462,8 @@ class Parser
2415
  break;
2416
  }
2417
 
2418
- // peek and see if rhs belongs to next operator
2419
- if ($this->peek($operators, $next) && static::$precedence[$next[1]] > static::$precedence[$op]) {
2420
- $rhs = $this->expHelper($rhs, static::$precedence[$next[1]]);
2421
- }
2422
 
2423
  $lhs = [Type::T_EXPRESSION, $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter];
2424
 
@@ -2437,7 +2482,7 @@ class Parser
2437
  *
2438
  * @param array $out
2439
  *
2440
- * @return boolean
2441
  */
2442
  protected function value(&$out)
2443
  {
@@ -2645,7 +2690,7 @@ class Parser
2645
  *
2646
  * @param array $out
2647
  *
2648
- * @return boolean
2649
  */
2650
  protected function parenValue(&$out)
2651
  {
@@ -2684,7 +2729,7 @@ class Parser
2684
  *
2685
  * @param array $out
2686
  *
2687
- * @return boolean
2688
  */
2689
  protected function progid(&$out)
2690
  {
@@ -2717,7 +2762,7 @@ class Parser
2717
  * @param string $name
2718
  * @param array $func
2719
  *
2720
- * @return boolean
2721
  */
2722
  protected function func($name, &$func)
2723
  {
@@ -2771,7 +2816,7 @@ class Parser
2771
  *
2772
  * @param array $out
2773
  *
2774
- * @return boolean
2775
  */
2776
  protected function argumentList(&$out)
2777
  {
@@ -2816,7 +2861,7 @@ class Parser
2816
  *
2817
  * @param array $out
2818
  *
2819
- * @return boolean
2820
  */
2821
  protected function argumentDef(&$out)
2822
  {
@@ -2878,7 +2923,7 @@ class Parser
2878
  *
2879
  * @param array $out
2880
  *
2881
- * @return boolean
2882
  */
2883
  protected function map(&$out)
2884
  {
@@ -2920,7 +2965,7 @@ class Parser
2920
  *
2921
  * @param array $out
2922
  *
2923
- * @return boolean
2924
  */
2925
  protected function color(&$out)
2926
  {
@@ -2946,7 +2991,7 @@ class Parser
2946
  *
2947
  * @param array $unit
2948
  *
2949
- * @return boolean
2950
  */
2951
  protected function unit(&$unit)
2952
  {
@@ -2971,8 +3016,9 @@ class Parser
2971
  * Parse string
2972
  *
2973
  * @param array $out
 
2974
  *
2975
- * @return boolean
2976
  */
2977
  protected function string(&$out, $keepDelimWithInterpolation = false)
2978
  {
@@ -3053,7 +3099,8 @@ class Parser
3053
 
3054
  /**
3055
  * @param string $out
3056
- * @param bool $inKeywords
 
3057
  * @return bool
3058
  */
3059
  protected function matchEscapeCharacter(&$out, $inKeywords = false)
@@ -3103,10 +3150,10 @@ class Parser
3103
  /**
3104
  * Parse keyword or interpolation
3105
  *
3106
- * @param array $out
3107
- * @param boolean $restricted
3108
  *
3109
- * @return boolean
3110
  */
3111
  protected function mixedKeyword(&$out, $restricted = false)
3112
  {
@@ -3147,14 +3194,14 @@ class Parser
3147
  /**
3148
  * Parse an unbounded string stopped by $end
3149
  *
3150
- * @param string $end
3151
- * @param array $out
3152
- * @param string $nestOpen
3153
- * @param string $nestClose
3154
- * @param boolean $rtrim
3155
  * @param string $disallow
3156
  *
3157
- * @return boolean
3158
  */
3159
  protected function openString($end, &$out, $nestOpen = null, $nestClose = null, $rtrim = true, $disallow = null)
3160
  {
@@ -3230,9 +3277,9 @@ class Parser
3230
  * Parser interpolation
3231
  *
3232
  * @param string|array $out
3233
- * @param boolean $lookWhite save information about whitespace before and after
3234
  *
3235
- * @return boolean
3236
  */
3237
  protected function interpolation(&$out, $lookWhite = true)
3238
  {
@@ -3287,7 +3334,7 @@ class Parser
3287
  *
3288
  * @param array $out
3289
  *
3290
- * @return boolean
3291
  */
3292
  protected function propertyName(&$out)
3293
  {
@@ -3342,7 +3389,7 @@ class Parser
3342
  *
3343
  * @param array $out
3344
  *
3345
- * @return boolean
3346
  */
3347
  protected function customProperty(&$out)
3348
  {
@@ -3400,9 +3447,9 @@ class Parser
3400
  * Parse comma separated selector list
3401
  *
3402
  * @param array $out
3403
- * @param string|boolean $subSelector
3404
  *
3405
- * @return boolean
3406
  */
3407
  protected function selectors(&$out, $subSelector = false)
3408
  {
@@ -3436,9 +3483,9 @@ class Parser
3436
  * Parse whitespace separated selector list
3437
  *
3438
  * @param array $out
3439
- * @param string|boolean $subSelector
3440
  *
3441
- * @return boolean
3442
  */
3443
  protected function selector(&$out, $subSelector = false)
3444
  {
@@ -3494,7 +3541,8 @@ class Parser
3494
  * - but this require a better formal selector representation instead of the array we have now
3495
  *
3496
  * @param string $out
3497
- * @param bool $keepEscapedNumber
 
3498
  * @return bool
3499
  */
3500
  protected function matchEscapeCharacterInSelector(&$out, $keepEscapedNumber = false)
@@ -3539,9 +3587,9 @@ class Parser
3539
  * }}
3540
  *
3541
  * @param array $out
3542
- * @param string|boolean $subSelector
3543
  *
3544
- * @return boolean
3545
  */
3546
  protected function selectorSingle(&$out, $subSelector = false)
3547
  {
@@ -3765,7 +3813,7 @@ class Parser
3765
  *
3766
  * @param array $out
3767
  *
3768
- * @return boolean
3769
  */
3770
  protected function variable(&$out)
3771
  {
@@ -3792,11 +3840,11 @@ class Parser
3792
  /**
3793
  * Parse a keyword
3794
  *
3795
- * @param string $word
3796
- * @param boolean $eatWhitespace
3797
- * @param boolean $inSelector
3798
  *
3799
- * @return boolean
3800
  */
3801
  protected function keyword(&$word, $eatWhitespace = null, $inSelector = false)
3802
  {
@@ -3859,11 +3907,11 @@ class Parser
3859
  /**
3860
  * Parse a keyword that should not start with a number
3861
  *
3862
- * @param string $word
3863
- * @param boolean $eatWhitespace
3864
- * @param boolean $inSelector
3865
  *
3866
- * @return boolean
3867
  */
3868
  protected function restrictedKeyword(&$word, $eatWhitespace = null, $inSelector = false)
3869
  {
@@ -3883,7 +3931,7 @@ class Parser
3883
  *
3884
  * @param string|array $placeholder
3885
  *
3886
- * @return boolean
3887
  */
3888
  protected function placeholder(&$placeholder)
3889
  {
@@ -3912,7 +3960,7 @@ class Parser
3912
  *
3913
  * @param array $out
3914
  *
3915
- * @return boolean
3916
  */
3917
  protected function url(&$out)
3918
  {
@@ -3947,7 +3995,7 @@ class Parser
3947
  * Consume an end of statement delimiter
3948
  * @param bool $eatWhitespace
3949
  *
3950
- * @return boolean
3951
  */
3952
  protected function end($eatWhitespace = null)
3953
  {
@@ -4065,7 +4113,7 @@ class Parser
4065
  /**
4066
  * Get source line number and column (given character position in the buffer)
4067
  *
4068
- * @param integer $pos
4069
  *
4070
  * @return array
4071
  */
12
 
13
  namespace ScssPhp\ScssPhp;
14
 
15
+ use ScssPhp\ScssPhp\Block\AtRootBlock;
16
+ use ScssPhp\ScssPhp\Block\CallableBlock;
17
+ use ScssPhp\ScssPhp\Block\ContentBlock;
18
+ use ScssPhp\ScssPhp\Block\DirectiveBlock;
19
+ use ScssPhp\ScssPhp\Block\EachBlock;
20
+ use ScssPhp\ScssPhp\Block\ElseBlock;
21
+ use ScssPhp\ScssPhp\Block\ElseifBlock;
22
+ use ScssPhp\ScssPhp\Block\ForBlock;
23
+ use ScssPhp\ScssPhp\Block\IfBlock;
24
+ use ScssPhp\ScssPhp\Block\MediaBlock;
25
+ use ScssPhp\ScssPhp\Block\NestedPropertyBlock;
26
+ use ScssPhp\ScssPhp\Block\WhileBlock;
27
  use ScssPhp\ScssPhp\Exception\ParserException;
28
  use ScssPhp\ScssPhp\Logger\LoggerInterface;
29
  use ScssPhp\ScssPhp\Logger\QuietLogger;
137
  * @api
138
  *
139
  * @param string|null $sourceName
140
+ * @param int $sourceIndex
141
  * @param string|null $encoding
142
  * @param Cache|null $cache
143
  * @param bool $cssOnly
317
  * @param string $buffer
318
  * @param string|array $out
319
  *
320
+ * @return bool
321
  */
322
  public function parseValue($buffer, &$out)
323
  {
346
  * @param string|array $out
347
  * @param bool $shouldValidate
348
  *
349
+ * @return bool
350
  */
351
  public function parseSelector($buffer, &$out, $shouldValidate = true)
352
  {
383
  * @param string $buffer
384
  * @param string|array $out
385
  *
386
+ * @return bool
387
  */
388
  public function parseMediaQueryList($buffer, &$out)
389
  {
440
  * position into $s. Then if a chain fails, use $this->seek($s) to
441
  * go back where we started.
442
  *
443
+ * @return bool
444
  */
445
  protected function parseChunk()
446
  {
459
  ) {
460
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
461
 
462
+ $atRoot = new AtRootBlock();
463
+ $this->registerPushedBlock($atRoot, $s);
464
  $atRoot->selector = $selector;
465
  $atRoot->with = $with;
466
 
474
  $this->mediaQueryList($mediaQueryList) &&
475
  $this->matchChar('{', false)
476
  ) {
477
+ $media = new MediaBlock();
478
+ $this->registerPushedBlock($media, $s);
479
  $media->queryList = $mediaQueryList[2];
480
 
481
  return true;
491
  ) {
492
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
493
 
494
+ $mixin = new CallableBlock(Type::T_MIXIN);
495
+ $this->registerPushedBlock($mixin, $s);
496
  $mixin->name = $mixinName;
497
  $mixin->args = $args;
498
 
524
  ];
525
 
526
  if (! empty($hasBlock)) {
527
+ $include = new ContentBlock();
528
+ $this->registerPushedBlock($include, $s);
529
  $include->child = $child;
530
  } else {
531
  $this->append($child, $s);
615
  ) {
616
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
617
 
618
+ $func = new CallableBlock(Type::T_FUNCTION);
619
+ $this->registerPushedBlock($func, $s);
620
  $func->name = $fnName;
621
  $func->args = $args;
622
 
648
  ) {
649
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
650
 
651
+ $each = new EachBlock();
652
+ $this->registerPushedBlock($each, $s);
653
 
654
  foreach ($varNames[2] as $varName) {
655
  $each->vars[] = $varName[1];
678
  $cond = reset($cond[2]);
679
  }
680
 
681
+ $while = new WhileBlock();
682
+ $this->registerPushedBlock($while, $s);
683
  $while->cond = $cond;
684
 
685
  return true;
699
  ) {
700
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
701
 
702
+ $for = new ForBlock();
703
+ $this->registerPushedBlock($for, $s);
704
  $for->var = $varName[1];
705
  $for->start = $start;
706
  $for->end = $end;
717
  ) {
718
  ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
719
 
720
+ $if = new IfBlock();
721
+ $this->registerPushedBlock($if, $s);
722
 
723
  while (
724
  $cond[0] === Type::T_LIST &&
797
 
798
  if (isset($last) && $last[0] === Type::T_IF) {
799
  list(, $if) = $last;
800
+ assert($if instanceof IfBlock);
801
 
802
  if ($this->literal('@else', 5)) {
803
  if ($this->matchChar('{', false)) {
804
+ $else = new ElseBlock();
805
  } elseif (
806
  $this->literal('if', 2) &&
807
  $this->functionCallArgumentsList($cond, false, '{', false)
808
  ) {
809
+ $else = new ElseifBlock();
810
  $else->cond = $cond;
811
  }
812
 
813
  if (isset($else)) {
814
+ $this->registerPushedBlock($else, $s);
815
  $if->cases[] = $else;
816
 
817
  return true;
849
  ($t1 = $this->supportsQuery($supportQuery)) &&
850
  ($t2 = $this->matchChar('{', false))
851
  ) {
852
+ $directive = new DirectiveBlock();
853
+ $this->registerPushedBlock($directive, $s);
854
  $directive->name = 'supports';
855
  $directive->value = $supportQuery;
856
 
871
  $dirName = [Type::T_STRING, '', $dirName];
872
  }
873
  if ($dirName === 'media') {
874
+ $directive = new MediaBlock();
875
  } else {
876
+ $directive = new DirectiveBlock();
877
  $directive->name = $dirName;
878
  }
879
+ $this->registerPushedBlock($directive, $s);
880
 
881
  if (isset($dirValue)) {
882
  ! $this->cssOnly || ($dirValue = $this->assertPlainCssValid($dirValue));
1052
  if ($this->matchChar('{', false)) {
1053
  ! $this->cssOnly || $this->assertPlainCssValid(false);
1054
 
1055
+ $propBlock = new NestedPropertyBlock();
1056
+ $this->registerPushedBlock($propBlock, $s);
1057
  $propBlock->prefix = $name;
1058
  $propBlock->hasValue = $foundSomething;
1059
 
1079
  }
1080
  }
1081
 
1082
+ if ($block instanceof ContentBlock) {
1083
  $include = $block->child;
1084
+ assert(\is_array($include));
1085
  unset($block->child);
1086
  $include[3] = $block;
1087
  $this->append($include, $s);
1088
+ } elseif (!$block instanceof ElseBlock && !$block instanceof ElseifBlock) {
1089
  $type = isset($block->type) ? $block->type : Type::T_BLOCK;
1090
  $this->append([$type, $block], $s);
1091
  }
1114
  * Push block onto parse tree
1115
  *
1116
  * @param array|null $selectors
1117
+ * @param int $pos
1118
  *
1119
  * @return Block
1120
  */
1121
  protected function pushBlock($selectors, $pos = 0)
1122
+ {
1123
+ $b = new Block();
1124
+ $b->selectors = $selectors;
1125
+
1126
+ $this->registerPushedBlock($b, $pos);
1127
+
1128
+ return $b;
1129
+ }
1130
+
1131
+ /**
1132
+ * @param Block $b
1133
+ * @param int $pos
1134
+ *
1135
+ * @return void
1136
+ */
1137
+ private function registerPushedBlock(Block $b, $pos)
1138
  {
1139
  list($line, $column) = $this->getSourcePosition($pos);
1140
 
 
1141
  $b->sourceName = $this->sourceName;
1142
  $b->sourceLine = $line;
1143
  $b->sourceColumn = $column;
1144
  $b->sourceIndex = $this->sourceIndex;
 
1145
  $b->comments = [];
1146
  $b->parent = $this->env;
1147
 
1166
  $this->append(null);
1167
  }
1168
  }
 
 
1169
  }
1170
 
1171
  /**
1172
  * Push special (named) block onto parse tree
1173
  *
1174
+ * @deprecated
1175
+ *
1176
  * @param string $type
1177
+ * @param int $pos
1178
  *
1179
  * @return Block
1180
  */
1223
  /**
1224
  * Peek input stream
1225
  *
1226
+ * @param string $regex
1227
+ * @param array $out
1228
+ * @param int $from
1229
  *
1230
+ * @return int
1231
  */
1232
  protected function peek($regex, &$out, $from = null)
1233
  {
1244
  /**
1245
  * Seek to position in input stream (or return current position in input stream)
1246
  *
1247
+ * @param int $where
1248
  */
1249
  protected function seek($where)
1250
  {
1255
  * Assert a parsed part is plain CSS Valid
1256
  *
1257
  * @param array|false $parsed
1258
+ * @param int $startPos
1259
+ *
1260
  * @throws ParserException
1261
  */
1262
  protected function assertPlainCssValid($parsed, $startPos = null)
1284
 
1285
  /**
1286
  * Check a parsed element is plain CSS Valid
1287
+ *
1288
  * @param array $parsed
1289
+ * @param bool $allowExpression
1290
+ *
1291
  * @return bool|array
1292
  */
1293
  protected function isPlainCssValidElement($parsed, $allowExpression = false)
1467
  * @param array $m Matches (passed by reference)
1468
  * @param string $delim Delimiter
1469
  *
1470
+ * @return bool True if match; false otherwise
1471
  */
1472
  protected function matchString(&$m, $delim)
1473
  {
1503
  /**
1504
  * Try to match something on head of buffer
1505
  *
1506
+ * @param string $regex
1507
+ * @param array $out
1508
+ * @param bool $eatWhitespace
1509
  *
1510
+ * @return bool
1511
  */
1512
  protected function match($regex, &$out, $eatWhitespace = null)
1513
  {
1533
  /**
1534
  * Match a single string
1535
  *
1536
+ * @param string $char
1537
+ * @param bool $eatWhitespace
1538
  *
1539
+ * @return bool
1540
  */
1541
  protected function matchChar($char, $eatWhitespace = null)
1542
  {
1560
  /**
1561
  * Match literal string
1562
  *
1563
+ * @param string $what
1564
+ * @param int $len
1565
+ * @param bool $eatWhitespace
1566
  *
1567
+ * @return bool
1568
  */
1569
  protected function literal($what, $len, $eatWhitespace = null)
1570
  {
1588
  /**
1589
  * Match some whitespace
1590
  *
1591
+ * @return bool
1592
  */
1593
  protected function whitespace()
1594
  {
1624
  } else {
1625
  list($line, $column) = $this->getSourcePosition($this->count);
1626
  $file = $this->sourceName;
1627
+ if (!$this->discardComments) {
1628
+ $this->logger->warn("Unterminated interpolations in multiline comments are deprecated and will be removed in ScssPhp 2.0, in \"$file\", line $line, column $column.", true);
1629
+ }
1630
  $comment[] = substr($this->buffer, $this->count, 2);
1631
 
1632
  $this->count += 2;
1687
  * Append statement to current block
1688
  *
1689
  * @param array|null $statement
1690
+ * @param int $pos
1691
  */
1692
  protected function append($statement, $pos = null)
1693
  {
1732
  *
1733
  * @param array $out
1734
  *
1735
+ * @return bool
1736
  */
1737
  protected function mediaQueryList(&$out)
1738
  {
1744
  *
1745
  * @param array $out
1746
  *
1747
+ * @return bool
1748
  */
1749
  protected function mediaQuery(&$out)
1750
  {
1798
  *
1799
  * @param array $out
1800
  *
1801
+ * @return bool
1802
  */
1803
  protected function supportsQuery(&$out)
1804
  {
1931
  *
1932
  * @param array $out
1933
  *
1934
+ * @return bool
1935
  */
1936
  protected function mediaExpression(&$out)
1937
  {
1964
  *
1965
  * @param array $out
1966
  *
1967
+ * @return bool
1968
  */
1969
  protected function argValues(&$out)
1970
  {
1989
  *
1990
  * @param array $out
1991
  *
1992
+ * @return bool
1993
  */
1994
  protected function argValue(&$out)
1995
  {
2069
  /**
2070
  * Parse directive value list that considers $vars as keyword
2071
  *
2072
+ * @param array $out
2073
+ * @param bool|string $endChar
2074
  *
2075
+ * @return bool
2076
  */
2077
  protected function directiveValue(&$out, $endChar = false)
2078
  {
2133
  *
2134
  * @param array $out
2135
  *
2136
+ * @return bool
2137
  */
2138
  protected function valueList(&$out)
2139
  {
2149
  * Parse a function call, where externals () are part of the call
2150
  * and not of the value list
2151
  *
2152
+ * @param array $out
2153
+ * @param bool $mandatoryEnclos
2154
  * @param null|string $charAfter
2155
+ * @param null|bool $eatWhiteSp
2156
+ *
2157
  * @return bool
2158
  */
2159
  protected function functionCallArgumentsList(&$out, $mandatoryEnclos = true, $charAfter = null, $eatWhiteSp = null)
2190
  *
2191
  * @param array $out
2192
  *
2193
+ * @return bool
2194
  */
2195
  protected function spaceList(&$out)
2196
  {
2200
  /**
2201
  * Parse generic list
2202
  *
2203
+ * @param array $out
2204
+ * @param string $parseItem The name of the method used to parse items
2205
+ * @param string $delim
2206
+ * @param bool $flatten
2207
  *
2208
+ * @return bool
2209
  */
2210
  protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
2211
  {
2301
  /**
2302
  * Parse expression
2303
  *
2304
+ * @param array $out
2305
+ * @param bool $listOnly
2306
+ * @param bool $lookForExp
2307
  *
2308
+ * @return bool
2309
  */
2310
  protected function expression(&$out, $listOnly = false, $lookForExp = true)
2311
  {
2367
  * Parse expression specifically checking for lists in parenthesis or brackets
2368
  *
2369
  * @param array $out
2370
+ * @param int $s
2371
  * @param string $closingParen
2372
  * @param array $allowedTypes
2373
  *
2374
+ * @return bool
2375
  */
2376
  protected function enclosedExpression(&$out, $s, $closingParen = ')', $allowedTypes = [Type::T_LIST, Type::T_MAP])
2377
  {
2426
  /**
2427
  * Parse left-hand side of subexpression
2428
  *
2429
+ * @param array $lhs
2430
+ * @param int $minP
2431
  *
2432
  * @return array
2433
  */
2462
  break;
2463
  }
2464
 
2465
+ // consume higher-precedence operators on the right-hand side
2466
+ $rhs = $this->expHelper($rhs, static::$precedence[$op] + 1);
 
 
2467
 
2468
  $lhs = [Type::T_EXPRESSION, $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter];
2469
 
2482
  *
2483
  * @param array $out
2484
  *
2485
+ * @return bool
2486
  */
2487
  protected function value(&$out)
2488
  {
2690
  *
2691
  * @param array $out
2692
  *
2693
+ * @return bool
2694
  */
2695
  protected function parenValue(&$out)
2696
  {
2729
  *
2730
  * @param array $out
2731
  *
2732
+ * @return bool
2733
  */
2734
  protected function progid(&$out)
2735
  {
2762
  * @param string $name
2763
  * @param array $func
2764
  *
2765
+ * @return bool
2766
  */
2767
  protected function func($name, &$func)
2768
  {
2816
  *
2817
  * @param array $out
2818
  *
2819
+ * @return bool
2820
  */
2821
  protected function argumentList(&$out)
2822
  {
2861
  *
2862
  * @param array $out
2863
  *
2864
+ * @return bool
2865
  */
2866
  protected function argumentDef(&$out)
2867
  {
2923
  *
2924
  * @param array $out
2925
  *
2926
+ * @return bool
2927
  */
2928
  protected function map(&$out)
2929
  {
2965
  *
2966
  * @param array $out
2967
  *
2968
+ * @return bool
2969
  */
2970
  protected function color(&$out)
2971
  {
2991
  *
2992
  * @param array $unit
2993
  *
2994
+ * @return bool
2995
  */
2996
  protected function unit(&$unit)
2997
  {
3016
  * Parse string
3017
  *
3018
  * @param array $out
3019
+ * @param bool $keepDelimWithInterpolation
3020
  *
3021
+ * @return bool
3022
  */
3023
  protected function string(&$out, $keepDelimWithInterpolation = false)
3024
  {
3099
 
3100
  /**
3101
  * @param string $out
3102
+ * @param bool $inKeywords
3103
+ *
3104
  * @return bool
3105
  */
3106
  protected function matchEscapeCharacter(&$out, $inKeywords = false)
3150
  /**
3151
  * Parse keyword or interpolation
3152
  *
3153
+ * @param array $out
3154
+ * @param bool $restricted
3155
  *
3156
+ * @return bool
3157
  */
3158
  protected function mixedKeyword(&$out, $restricted = false)
3159
  {
3194
  /**
3195
  * Parse an unbounded string stopped by $end
3196
  *
3197
+ * @param string $end
3198
+ * @param array $out
3199
+ * @param string $nestOpen
3200
+ * @param string $nestClose
3201
+ * @param bool $rtrim
3202
  * @param string $disallow
3203
  *
3204
+ * @return bool
3205
  */
3206
  protected function openString($end, &$out, $nestOpen = null, $nestClose = null, $rtrim = true, $disallow = null)
3207
  {
3277
  * Parser interpolation
3278
  *
3279
  * @param string|array $out
3280
+ * @param bool $lookWhite save information about whitespace before and after
3281
  *
3282
+ * @return bool
3283
  */
3284
  protected function interpolation(&$out, $lookWhite = true)
3285
  {
3334
  *
3335
  * @param array $out
3336
  *
3337
+ * @return bool
3338
  */
3339
  protected function propertyName(&$out)
3340
  {
3389
  *
3390
  * @param array $out
3391
  *
3392
+ * @return bool
3393
  */
3394
  protected function customProperty(&$out)
3395
  {
3447
  * Parse comma separated selector list
3448
  *
3449
  * @param array $out
3450
+ * @param string|bool $subSelector
3451
  *
3452
+ * @return bool
3453
  */
3454
  protected function selectors(&$out, $subSelector = false)
3455
  {
3483
  * Parse whitespace separated selector list
3484
  *
3485
  * @param array $out
3486
+ * @param string|bool $subSelector
3487
  *
3488
+ * @return bool
3489
  */
3490
  protected function selector(&$out, $subSelector = false)
3491
  {
3541
  * - but this require a better formal selector representation instead of the array we have now
3542
  *
3543
  * @param string $out
3544
+ * @param bool $keepEscapedNumber
3545
+ *
3546
  * @return bool
3547
  */
3548
  protected function matchEscapeCharacterInSelector(&$out, $keepEscapedNumber = false)
3587
  * }}
3588
  *
3589
  * @param array $out
3590
+ * @param string|bool $subSelector
3591
  *
3592
+ * @return bool
3593
  */
3594
  protected function selectorSingle(&$out, $subSelector = false)
3595
  {
3813
  *
3814
  * @param array $out
3815
  *
3816
+ * @return bool
3817
  */
3818
  protected function variable(&$out)
3819
  {
3840
  /**
3841
  * Parse a keyword
3842
  *
3843
+ * @param string $word
3844
+ * @param bool $eatWhitespace
3845
+ * @param bool $inSelector
3846
  *
3847
+ * @return bool
3848
  */
3849
  protected function keyword(&$word, $eatWhitespace = null, $inSelector = false)
3850
  {
3907
  /**
3908
  * Parse a keyword that should not start with a number
3909
  *
3910
+ * @param string $word
3911
+ * @param bool $eatWhitespace
3912
+ * @param bool $inSelector
3913
  *
3914
+ * @return bool
3915
  */
3916
  protected function restrictedKeyword(&$word, $eatWhitespace = null, $inSelector = false)
3917
  {
3931
  *
3932
  * @param string|array $placeholder
3933
  *
3934
+ * @return bool
3935
  */
3936
  protected function placeholder(&$placeholder)
3937
  {
3960
  *
3961
  * @param array $out
3962
  *
3963
+ * @return bool
3964
  */
3965
  protected function url(&$out)
3966
  {
3995
  * Consume an end of statement delimiter
3996
  * @param bool $eatWhitespace
3997
  *
3998
+ * @return bool
3999
  */
4000
  protected function end($eatWhitespace = null)
4001
  {
4113
  /**
4114
  * Get source line number and column (given character position in the buffer)
4115
  *
4116
+ * @param int $pos
4117
  *
4118
  * @return array
4119
  */
scssphp/src/SourceMap/Base64.php CHANGED
@@ -164,7 +164,7 @@ class Base64
164
  /**
165
  * Convert to base64
166
  *
167
- * @param integer $value
168
  *
169
  * @return string
170
  */
@@ -178,7 +178,7 @@ class Base64
178
  *
179
  * @param string $value
180
  *
181
- * @return integer
182
  */
183
  public static function decode($value)
184
  {
164
  /**
165
  * Convert to base64
166
  *
167
+ * @param int $value
168
  *
169
  * @return string
170
  */
178
  *
179
  * @param string $value
180
  *
181
+ * @return int
182
  */
183
  public static function decode($value)
184
  {
scssphp/src/SourceMap/Base64VLQ.php CHANGED
@@ -51,7 +51,7 @@ class Base64VLQ
51
  /**
52
  * Returns the VLQ encoded value.
53
  *
54
- * @param integer $value
55
  *
56
  * @return string
57
  */
@@ -80,9 +80,9 @@ class Base64VLQ
80
  * Decodes VLQValue.
81
  *
82
  * @param string $str
83
- * @param integer $index
84
  *
85
- * @return integer
86
  */
87
  public static function decode($str, &$index)
88
  {
@@ -107,9 +107,9 @@ class Base64VLQ
107
  * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
108
  * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
109
  *
110
- * @param integer $value
111
  *
112
- * @return integer
113
  */
114
  private static function toVLQSigned($value)
115
  {
@@ -126,9 +126,9 @@ class Base64VLQ
126
  * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
127
  * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
128
  *
129
- * @param integer $value
130
  *
131
- * @return integer
132
  */
133
  private static function fromVLQSigned($value)
134
  {
51
  /**
52
  * Returns the VLQ encoded value.
53
  *
54
+ * @param int $value
55
  *
56
  * @return string
57
  */
80
  * Decodes VLQValue.
81
  *
82
  * @param string $str
83
+ * @param int $index
84
  *
85
+ * @return int
86
  */
87
  public static function decode($str, &$index)
88
  {
107
  * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
108
  * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
109
  *
110
+ * @param int $value
111
  *
112
+ * @return int
113
  */
114
  private static function toVLQSigned($value)
115
  {
126
  * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
127
  * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
128
  *
129
+ * @param int $value
130
  *
131
+ * @return int
132
  */
133
  private static function fromVLQSigned($value)
134
  {
scssphp/src/SourceMap/SourceMapGenerator.php CHANGED
@@ -114,11 +114,11 @@ class SourceMapGenerator
114
  /**
115
  * Adds a mapping
116
  *
117
- * @param integer $generatedLine The line number in generated file
118
- * @param integer $generatedColumn The column number in generated file
119
- * @param integer $originalLine The line number in original file
120
- * @param integer $originalColumn The column number in original file
121
- * @param string $sourceFile The original source file
122
  *
123
  * @return void
124
  */
@@ -326,7 +326,7 @@ class SourceMapGenerator
326
  *
327
  * @param string $filename
328
  *
329
- * @return integer|false
330
  */
331
  protected function findFileIndex($filename)
332
  {
@@ -362,8 +362,8 @@ class SourceMapGenerator
362
  /**
363
  * Fix windows paths
364
  *
365
- * @param string $path
366
- * @param boolean $addEndSlash
367
  *
368
  * @return string
369
  */
114
  /**
115
  * Adds a mapping
116
  *
117
+ * @param int $generatedLine The line number in generated file
118
+ * @param int $generatedColumn The column number in generated file
119
+ * @param int $originalLine The line number in original file
120
+ * @param int $originalColumn The column number in original file
121
+ * @param string $sourceFile The original source file
122
  *
123
  * @return void
124
  */
326
  *
327
  * @param string $filename
328
  *
329
+ * @return int|false
330
  */
331
  protected function findFileIndex($filename)
332
  {
362
  /**
363
  * Fix windows paths
364
  *
365
+ * @param string $path
366
+ * @param bool $addEndSlash
367
  *
368
  * @return string
369
  */
scssphp/src/Type.php CHANGED
@@ -19,58 +19,190 @@ namespace ScssPhp\ScssPhp;
19
  */
20
  class Type
21
  {
 
 
 
22
  const T_ASSIGN = 'assign';
 
 
 
23
  const T_AT_ROOT = 'at-root';
 
 
 
24
  const T_BLOCK = 'block';
25
- /** @deprecated */
 
 
 
26
  const T_BREAK = 'break';
 
 
 
27
  const T_CHARSET = 'charset';
28
  const T_COLOR = 'color';
 
 
 
29
  const T_COMMENT = 'comment';
30
- /** @deprecated */
 
 
 
31
  const T_CONTINUE = 'continue';
32
- /** @deprecated */
 
 
 
33
  const T_CONTROL = 'control';
 
 
 
34
  const T_CUSTOM_PROPERTY = 'custom';
 
 
 
35
  const T_DEBUG = 'debug';
 
 
 
36
  const T_DIRECTIVE = 'directive';
 
 
 
37
  const T_EACH = 'each';
 
 
 
38
  const T_ELSE = 'else';
 
 
 
39
  const T_ELSEIF = 'elseif';
 
 
 
40
  const T_ERROR = 'error';
 
 
 
41
  const T_EXPRESSION = 'exp';
 
 
 
42
  const T_EXTEND = 'extend';
 
 
 
43
  const T_FOR = 'for';
44
  const T_FUNCTION = 'function';
 
 
 
45
  const T_FUNCTION_REFERENCE = 'function-reference';
 
 
 
46
  const T_FUNCTION_CALL = 'fncall';
 
 
 
47
  const T_HSL = 'hsl';
 
 
 
48
  const T_HWB = 'hwb';
 
 
 
49
  const T_IF = 'if';
 
 
 
50
  const T_IMPORT = 'import';
 
 
 
51
  const T_INCLUDE = 'include';
 
 
 
52
  const T_INTERPOLATE = 'interpolate';
 
 
 
53
  const T_INTERPOLATED = 'interpolated';
 
 
 
54
  const T_KEYWORD = 'keyword';
55
  const T_LIST = 'list';
56
  const T_MAP = 'map';
 
 
 
57
  const T_MEDIA = 'media';
 
 
 
58
  const T_MEDIA_EXPRESSION = 'mediaExp';
 
 
 
59
  const T_MEDIA_TYPE = 'mediaType';
 
 
 
60
  const T_MEDIA_VALUE = 'mediaValue';
 
 
 
61
  const T_MIXIN = 'mixin';
 
 
 
62
  const T_MIXIN_CONTENT = 'mixin_content';
 
 
 
63
  const T_NESTED_PROPERTY = 'nestedprop';
 
 
 
64
  const T_NOT = 'not';
65
  const T_NULL = 'null';
66
  const T_NUMBER = 'number';
 
 
 
67
  const T_RETURN = 'return';
 
 
 
68
  const T_ROOT = 'root';
 
 
 
69
  const T_SCSSPHP_IMPORT_ONCE = 'scssphp-import-once';
 
 
 
70
  const T_SELF = 'self';
71
  const T_STRING = 'string';
 
 
 
72
  const T_UNARY = 'unary';
 
 
 
73
  const T_VARIABLE = 'var';
 
 
 
74
  const T_WARN = 'warn';
 
 
 
75
  const T_WHILE = 'while';
76
  }
19
  */
20
  class Type
21
  {
22
+ /**
23
+ * @internal
24
+ */
25
  const T_ASSIGN = 'assign';
26
+ /**
27
+ * @internal
28
+ */
29
  const T_AT_ROOT = 'at-root';
30
+ /**
31
+ * @internal
32
+ */
33
  const T_BLOCK = 'block';
34
+ /**
35
+ * @deprecated
36
+ * @internal
37
+ */
38
  const T_BREAK = 'break';
39
+ /**
40
+ * @internal
41
+ */
42
  const T_CHARSET = 'charset';
43
  const T_COLOR = 'color';
44
+ /**
45
+ * @internal
46
+ */
47
  const T_COMMENT = 'comment';
48
+ /**
49
+ * @deprecated
50
+ * @internal
51
+ */
52
  const T_CONTINUE = 'continue';
53
+ /**
54
+ * @deprecated
55
+ * @internal
56
+ */
57
  const T_CONTROL = 'control';
58
+ /**
59
+ * @internal
60
+ */
61
  const T_CUSTOM_PROPERTY = 'custom';
62
+ /**
63
+ * @internal
64
+ */
65
  const T_DEBUG = 'debug';
66
+ /**
67
+ * @internal
68
+ */
69
  const T_DIRECTIVE = 'directive';
70
+ /**
71
+ * @internal
72
+ */
73
  const T_EACH = 'each';
74
+ /**
75
+ * @internal
76
+ */
77
  const T_ELSE = 'else';
78
+ /**
79
+ * @internal
80
+ */
81
  const T_ELSEIF = 'elseif';
82
+ /**
83
+ * @internal
84
+ */
85
  const T_ERROR = 'error';
86
+ /**
87
+ * @internal
88
+ */
89
  const T_EXPRESSION = 'exp';
90
+ /**
91
+ * @internal
92
+ */
93
  const T_EXTEND = 'extend';
94
+ /**
95
+ * @internal
96
+ */
97
  const T_FOR = 'for';
98
  const T_FUNCTION = 'function';
99
+ /**
100
+ * @internal
101
+ */
102
  const T_FUNCTION_REFERENCE = 'function-reference';
103
+ /**
104
+ * @internal
105
+ */
106
  const T_FUNCTION_CALL = 'fncall';
107
+ /**
108
+ * @internal
109
+ */
110
  const T_HSL = 'hsl';
111
+ /**
112
+ * @internal
113
+ */
114
  const T_HWB = 'hwb';
115
+ /**
116
+ * @internal
117
+ */
118
  const T_IF = 'if';
119
+ /**
120
+ * @internal
121
+ */
122
  const T_IMPORT = 'import';
123
+ /**
124
+ * @internal
125
+ */
126
  const T_INCLUDE = 'include';
127
+ /**
128
+ * @internal
129
+ */
130
  const T_INTERPOLATE = 'interpolate';
131
+ /**
132
+ * @internal
133
+ */
134
  const T_INTERPOLATED = 'interpolated';
135
+ /**
136
+ * @internal
137
+ */
138
  const T_KEYWORD = 'keyword';
139
  const T_LIST = 'list';
140
  const T_MAP = 'map';
141
+ /**
142
+ * @internal
143
+ */
144
  const T_MEDIA = 'media';
145
+ /**
146
+ * @internal
147
+ */
148
  const T_MEDIA_EXPRESSION = 'mediaExp';
149
+ /**
150
+ * @internal
151
+ */
152
  const T_MEDIA_TYPE = 'mediaType';
153
+ /**
154
+ * @internal
155
+ */
156
  const T_MEDIA_VALUE = 'mediaValue';
157
+ /**
158
+ * @internal
159
+ */
160
  const T_MIXIN = 'mixin';
161
+ /**
162
+ * @internal
163
+ */
164
  const T_MIXIN_CONTENT = 'mixin_content';
165
+ /**
166
+ * @internal
167
+ */
168
  const T_NESTED_PROPERTY = 'nestedprop';
169
+ /**
170
+ * @internal
171
+ */
172
  const T_NOT = 'not';
173
  const T_NULL = 'null';
174
  const T_NUMBER = 'number';
175
+ /**
176
+ * @internal
177
+ */
178
  const T_RETURN = 'return';
179
+ /**
180
+ * @internal
181
+ */
182
  const T_ROOT = 'root';
183
+ /**
184
+ * @internal
185
+ */
186
  const T_SCSSPHP_IMPORT_ONCE = 'scssphp-import-once';
187
+ /**
188
+ * @internal
189
+ */
190
  const T_SELF = 'self';
191
  const T_STRING = 'string';
192
+ /**
193
+ * @internal
194
+ */
195
  const T_UNARY = 'unary';
196
+ /**
197
+ * @internal
198
+ */
199
  const T_VARIABLE = 'var';
200
+ /**
201
+ * @internal
202
+ */
203
  const T_WARN = 'warn';
204
+ /**
205
+ * @internal
206
+ */
207
  const T_WHILE = 'while';
208
  }
scssphp/src/Util.php CHANGED
@@ -79,7 +79,7 @@ class Util
79
  /**
80
  * mb_chr() wrapper
81
  *
82
- * @param integer $code
83
  *
84
  * @return string
85
  */
79
  /**
80
  * mb_chr() wrapper
81
  *
82
+ * @param int $code
83
  *
84
  * @return string
85
  */
scssphp/src/Version.php CHANGED
@@ -19,5 +19,5 @@ namespace ScssPhp\ScssPhp;
19
  */
20
  class Version
21
  {
22
- const VERSION = '1.5.2';
23
  }
19
  */
20
  class Version
21
  {
22
+ const VERSION = '1.10.0';
23
  }
wp-scss.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WP-SCSS
4
  * Plugin URI: https://github.com/ConnectThink/WP-SCSS
5
  * Description: Compiles scss files live on WordPress.
6
- * Version: 2.4.0
7
  * Author: Connect Think
8
  * Author URI: http://connectthink.com
9
  * License: GPLv3
@@ -44,7 +44,7 @@ if (!defined('WPSCSS_VERSION_KEY'))
44
  define('WPSCSS_VERSION_KEY', 'wpscss_version');
45
 
46
  if (!defined('WPSCSS_VERSION_NUM'))
47
- define('WPSCSS_VERSION_NUM', '2.4.0');
48
 
49
  // Add version to options table
50
  if ( get_option( WPSCSS_VERSION_KEY ) !== false ) {
3
  * Plugin Name: WP-SCSS
4
  * Plugin URI: https://github.com/ConnectThink/WP-SCSS
5
  * Description: Compiles scss files live on WordPress.
6
+ * Version: 3.0.0
7
  * Author: Connect Think
8
  * Author URI: http://connectthink.com
9
  * License: GPLv3
44
  define('WPSCSS_VERSION_KEY', 'wpscss_version');
45
 
46
  if (!defined('WPSCSS_VERSION_NUM'))
47
+ define('WPSCSS_VERSION_NUM', '3.0.0');
48
 
49
  // Add version to options table
50
  if ( get_option( WPSCSS_VERSION_KEY ) !== false ) {